System.Addin or "Games with reliable plugins." Part 1


    Good day. I think that the vast majority of you have come across the problem of application extensibility. In the same way, I think that many of you had to dig Reflection to find out if the assembly is a plugin for your program. Many did not like the fact that in .NET assemblies are loaded by default into the same domain with the application, and then they could not be unloaded. Many, of course, created objects in separate domains through CreateInstanceAndUnwrap, but all this had to be done by hand. In general, "the mice cried and pricked ...". With the advent of System.Addin, developers got their hands on a tool for creating an extensible application that is devoid of these problems, as they say, out of the box. I will talk about this technology in several articles.

    Before we begin, let's deal with the terminology:
    A host, a host application is, in fact, an extensible application, which, as a rule, searches for and activates extensions.
    Addin, An extension is a module that contains some additional functionality for a host application.

    Features of System.Addin

    What is System.Addin? This is the new namespace that appeared in the .NET Framework 3.5. At its core, System.Addin provides developers with a programming model for extending application functionality. Moreover, the use of this software model provides several key features:

    1. The host application and Addin may have independent versions. Thus, it is possible to build a host application that would work with extension assemblies that were built for previous versions of the application, or for later versions of the application, or that were generally built for another application.

    2. Ability to activate Addin with the right level of isolation and security rights. That is, the program model System.Addin allows you to take care of the security of the application even if Addin was created by third-party developers. Now no important extension module will overwhelm your program.

    3. Support for multiple isolation levels of the extension from the host application and other extensions. That is, there are several possible scenarios for building isolation at the domain or process level, which enhances the security of the host application.

    4. More convenient life management extension. Since isolation is used at the domain or process level, upon completion of work with the plugin it is enough to simply unload the necessary domain.

    Okay With some features sorted out. Move on.


    The entire architecture of System.Addin is built around such a key concept as the Add-in pipeline (I would translate it as an “extension pipeline”). Under this phrase, in fact, everything is hidden. We look at the following figure, clarifying everything with architecture:


    This is the same Add-in pipeline . Due to all these segments, the necessary level of abstraction is achieved in the pipeline and isolation is ensured. We will analyze in more detail. At the ends of the pipeline, we see the host application and the extension itself. These are not the most interesting things, so let's get right to the consideration of what is between them:

    1. The contract . As can be seen from the figure, the contract is an interface, a “protocol of interaction” between the host and the extension, and is their common ground.

    2. Next, adapters are created on both sides of the contract (inherit Views), which implement the corresponding classes of the view (views)and wrap the contract with the interface that the view provides. Also, if you do not combine Addin view and Host view in one assembly, you can combine Host and Host view in one assembly. In any case, my advice to you: use a separate assembly for each segment of the pipeline. It will be easier.

    3. Well, the third point is the presentation classes (strictly must be interfaces, or inherited classes). They are the corresponding representations of types and methods that are used in the interaction of the host and the extension.

    At this stage, this information is enough for us. Just imagine how the Add-in pipeline looks. In more detail, we will consider the role of each of the segments of this pipeline in one of the following articles.
    It is also worth noting that the architecture imposes some limitations that we encounter during the creation process:

    1. Firstly, each segment from the conveyor is ideally a separate assembly. Views can be combined into one assembly, but only if the adapters are combined in the same way.

    2. Secondly, Addins, adapters and contracts must be public and marked with special attributes. See the picture below:

    Mandatory attributes are indicated with square brackets. As you can see, the view from the host side does not require a special attribute.

    3. Thirdly, a strict folder structure is required, which must be strictly observed for the normal functioning of the pipeline:


    * Addins do not necessarily lie next to adapters, views, and contracts. Extensions can be located anywhere.
    You can notice that each segment of the pipeline must be located in its own folder, and the AddInSideAdapters, AddInViews, Contracts and HostSideAdapters folders do not allow the presence of nested directories in them.

    4. Fourth, since the most typical scenario is with the activation of the extension in a separate domain, when designing, do not forget that the objects that cross the domain boundaries (as parameters or return values) must be serializable.

    Like this. No more, no less. The architecture and the restrictions imposed may seem unnecessarily complicated at first glance, but in reality this is not so. I think that now many of you realize what System.Addin
    is all about.

    In the next article, I will show an example demonstrating the use of System.Addin.

    Also popular now: