CLR AddIn Model in Paint.Net – 5 (IContract, ContractBase and AddInAdapter)

Once we load an AddIn in an AppDomain, we need to think about its lifetime management. There are questions like how to keep it alive in a remoting environment? What happens when we disconnect an AddIn with the host? When should we unload the AddIn appdomain? How to deal with multiple AddIns in a single AppDomain? How to pass AddIn objects around in the Host? Those are common question that most AddIn developers would ask sooner or later. Those questions have nothing to do with the core functionality of most AddIns. Therefore a common solution can be provided by a good AddIn model. Our model actually has a good answer for those questions already. We require all AddIn pipelines to follow the same basic Contract, System.AddIn.Contract.IContract. Coordination between Host and AddIn can be implemented by calling common functions of the contract. The contract looks like

 

 public interface IContract
{
      // Methods
      int AcquireLifetimeToken();
      int GetRemoteHashCode();
      IContract QueryContract(string contractIdentifier);
      bool RemoteEquals(IContract contract);
      string RemoteToString();
      void RevokeLifetimeToken(int token);

}

 

We also provided an implementation of IContract called System.AddIn.Pipeline.ContractBase (public class ContractBase : MarshalByRefObject, IContract, ISponsor). This ContractBase provides most functions from the AddIn side. It is marked as MarshalByRefObject for crossing AppDomain object reference. It is also the remoting sponsor for itself.

 

As we can see from the last blog, we have a Contract for Paint.Net called IPDNEffectContract. Now we need to implement this Contract at the AddIn side. Remember that we cannot have dependency between the Contract and AddIn; we need another Adapter here. AddInAdapter is the pipeline component to link the Contract and the AddIn. Here is our AddInAdapter.

 

namespace PaintDotNetAddInAdapter

{

    [AddInAdapter]

    public class PDNAddInAdapter : ContractBase, IPDNEffectContract

    {

        PDNAddInView addInView;

      public PDNAddInAdapter(PDNAddInView view)

        {

            addInView = view;

        }

        public void Render()

        {

            addInView.Render();

        }

    }

}

As we can see from its implementation, AddInAdapter got all the IContract implementation from ContractBase. The only task it really has is to implement IPDNEffectContract.

 

We also noticed a new type called PDNAddInView here. We have Host Side View. Now we have an AddInView. Why we need so many views in the whole pipeline? Here are my understandings. We want this model to be as complex as possible (kidding). Actually, first, we want one AddInAdapter to be able to be hooked up with multiple AddIns as long as they have the same view (AddInView abstract class). The same reasoning goes to the Host side. Second, AddInAdapter can easily consume another pipeline by simply treat another Host Side View as AddInView. This could be useful for some complex hosting scenarios.

 

Next topic will be AddInBase, AddIn and Deployment.