Using a WCF Custom Instance Provider

I recently developed a couple of WCF services that I wanted to share some common data, which I stored to and read from an XML file using standard serialization. (I didn’t want the trouble of setting up a database and writing code to access it.) And I didn’t want to load and save this file for every service call. So what I did was to create a custom instance provider that (a) loaded data from the file each time a service was instantiated and saved each time it was released and (b) passed a reference to the shared data to the created service instance.

First I created a class that implemented IInstanceProvider:

public class MyInstanceProvider : IInstanceProvider
{
    private static List<Case> caseList = null;

    #region IInstanceProvider Members

    public object GetInstance(InstanceContext instanceContext)
    {
        if (caseList == null)
            caseList = Load();
        return new TheService(logger, caseList);
    }

    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
        Save();
        if (instance is IDisposable)
            ((IDisposable)instance).Dispose();
    }

    #endregion
}

To be able to use this instance provider, I then created a custom attribute using this code:

public class CustomInstancingBehaviorAttribute : Attribute, IContractBehaviorAttribute, IContractBehavior
{
    #region IContractBehaviorAttribute Members

    public Type TargetContract
    {
        get { return typeof(ITheService); }
    }

    #endregion

    #region IContractBehavior Members

    public void AddBindingParameters(ContractDescription description, ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection parameters)
    {
        return;
    }

    public void ApplyClientBehavior(ContractDescription description, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        return;
    }

    public void ApplyDispatchBehavior(ContractDescription description, ServiceEndpoint endpoint, DispatchRuntime dispatch)
    {
        dispatch.InstanceProvider = new MyInstanceProvider();
    }

    public void Validate(ContractDescription description, ServiceEndpoint endpoint)
    {
        return;
    }

    #endregion
}

The important method above is ApplyDispatchBehavior that specifies that my instance provider should be used instead of the default one.

I could then use this attribute with my service implementation:

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Single)]
[CustomInstancingBehavior]
public class TheService : ITheService
{
    private Logger logger;
    private List<EcosCase> caseList;

    public TheService()
    {
    }

    public TheService(Logger logger, List<Case> caseList)
    {
        this.caseList = caseList;
    }

    …
}

The reason for specifying ConcurrencyMode.Single is that I did not want to write synchronization code to mitigate the risk that multiple threads could update the list simultaneously.

Advertisements

Getting Started with Host Application Integration with BizTalk Adapters for Host Systems 2.0 / Host Integration Server 2009

The documentation for BizTalk Adapters for Host Systems 2.0 / Host Integration Server 2009 is unfortunately not accurate (neither local help or the online version). I think they forgot to update it from the previous version. Here are some points that will help you getting started.

  • You must have Visual Studio with C++. Otherwise you will be able to run e.g. the BasicScenarios sample, but you cannot create your own project and add a library to it. (You will get the mysterious error messages “The system cannot find the file specified” and “Failed to save the library.”) (By the way, did know you that if you have installed Visual Studio 2008 SP1, you cannot install additional components, such as C++, without first uninstalling SP1? Try and you’ll get “A selected drive is no longer valid”.)
  • When creating your project, the Visual Studio template name is “Host Application”, not “Transaction Integrator Project”.
  • You cannot deploy from HIS designer in Visual Studio. You should go to TI Manager, expand Windows-Initiated Processing, right-click Objects and select New Object. Then point the wizard to your library (DLL).