Contracts, Views, and Adapters

This topic describes views and adapters, the segments that are common to both sides of the add-in pipeline, and the contract that is used by both the host and the add-in. The following illustration shows the segments of the add-in pipeline.

Add-in pipeline

Add-in pipeline model.

For code examples, see Walkthrough: Enabling Backward Compatibility as Your Host Changes and Walkthrough: Passing Collections Between Hosts and Add-Ins.

Contracts

The first step in developing the communication pipeline is to define a contract that must be derived from the IContract interface. If the host and the add-in are loaded into separate application domains, an isolation boundary exists between the add-in side of the pipeline and the host side of the pipeline. A contract is a non-versioning interface that defines the protocol for communicating types across an isolation boundary. By using contracts to communicate over an isolation boundary, the add-in model prevents the host's and add-in's implementations of the types from leaking across the boundary and causing versioning issues.

Objects that must be communicated across application domains must be remotable. For more information about remotable objects, see Remotable and Nonremotable Objects.

The ContractBase class provides a default implementation of IContract members. Your contract interface can also inherit this class.

Contract Requirements

Contracts must follow a set of requirements to ensure that all types expressed within the contracts are safe, can be versioned, and can pass across the isolation boundary between hosts and add-ins.

Contracts must inherit from IContract and must use only the following types:

  • Other contracts that are derived from IContract.

  • Primitive data types: integers and Boolean types.

  • Serializable types defined in the contract assembly.

  • Serializable types defined in Mscorlib.dll, such as Int32 and DateTime.

  • Sealed, serializable reference types. For example, you can pass a String object through the isolation boundary because it is a sealed, serializable reference type.

  • Enumerations that are defined in the contract or in Mscorlib.dll.

  • AddInToken objects.

  • Arrays of any of the preceding listed types, except an array of contracts.

To pass object collections, use types that implement the generic IList<T> interface, such as the List<T> and ArrayList collections. To pass these collections over the isolation boundary, you temporarily convert them to the IListContract<T> interface. The Walkthrough: Passing Collections Between Hosts and Add-Ins topic demonstrates how to pass collections.

To construct the pipeline, the contract that represents the add-in must be identified with the AddInContractAttribute attribute.

The next step in pipeline development is to create the view and adapter segments for both sides of the pipeline. These segments provide the host application and the add-in with views of their respective object models and provide adapters that convert those views to and from the contract.

Views

The add-in view of the host and the host view of the add-in are assemblies that contain interfaces or abstract classes that represent their views of each other and of the types that flow between them. Views are not dependant on the contracts used to communicate between them. Views also separate the add-in and host from each other's implementations. This allows the adapters and the contract to be changed without affecting the host or the add-in.

To construct the pipeline, the type in the add-in view that the add-in implements or inherits is identified by the AddInBaseAttribute attribute and is called the add-in base. The host view does not require an attribute for discoverability, because the host view is passed to the FindAddIns methods.

Adapters

The add-in-side and host-side adapters are assemblies that contain adapter classes that are used to convert to and from the views and the contract. The term "side" refers to the side of the pipeline that an adapter resides on. Depending on the direction of the call, the adapter is either converting from a view to a contract or from a contract to a view. If you have calls in both directions (that is, the host calls into the add-in and the add-in calls into the host), you will have two adapters on each side of the pipeline. Accordingly, there are two types of adapters:

  • View-to-contract adapter.

    A class in an adapter assembly that converts a view to a contract. This class implements the contract by calling into the view passed to its constructor and is marshaled across the boundary as a contract. This class must inherit ContractBase and implement the contract.

  • Contract-to-view adapter.

    A class in the adapter assembly that converts a contract to a view. This class implements or inherits the view segment that it is converting, depending on whether the view is an interface or an abstract base type, and implements the members of the view by calling into the contract that is passed to the adapter's constructor.

  • To construct the pipeline, you must identify the add-in-side adapter class by applying the AddInAdapterAttribute attribute, and identify the host-side adapter class by applying the HostAdapterAttribute attribute.

  • Adapters are not required to be public.

See Also

Concepts

Pipeline Development Requirements

Pipeline Development