wcfmefpolicy-injection

How to apply PIAB in WCF with MEF?


I have my service layer serving as a facade over my domain model layer to orchestrate calls to domain objects. I wrote a custome instance provider for my WCF services to harness MEF for instance creation. Now I need to apply PIAB for auditing and logging. How could I do it?


Solution

  • Jimmy Tonner has written a nice blog about mixing MEF and PIAB (visit http://blogs.msdn.com/b/jimmytr/archive/2010/06/22/mixing-mef-and-piab.aspx). It inspired my solution to applying PIAB to a MEFied WCF service. Idea is simple: use MEF to manage all your service composition first. Then in the custom instance provider, apply PolicyInjection.Wrap after locating the service instance by MEF container. Below is the code sample:

    Service:

    [Export(typeof(ICustomerService))]
    public class CustomerService : ICustomerService
    {
        #region ICustomerService Members
        public Customer GetCustomer(string customerID)
        {
            return CustomerDAO.GetCustomer(customerID);
        }
        #endregion
    }
    

    Custom instance provider:

    public class PolicyInjectionInstanceProvider : IInstanceProvider
    {
        private Type serviceContractType;
    
        private CompositionContainer Container { get; set; } 
    
        public PolicyInjectionInstanceProvider(Type t)
        {
    
            if (t!= null && !t.IsInterface)
            {
                throw new ArgumentException("Specified Type must be an interface");
            }
    
            this.serviceContractType = t;
    
        }
    
        #region IInstanceProvider Members
    
        public object GetInstance(InstanceContext instanceContext, System.ServiceModel.Channels.Message message)
        {
            Type type = instanceContext.Host.Description.ServiceType;
    
            if (serviceContractType != null)
            {
                Compose();
                var importDefinition = new ImportDefinition(i => i.ContractName.Equals(serviceContractType.FullName), serviceContractType.FullName, ImportCardinality.ZeroOrMore, false, false);
                var atomicComposition = new AtomicComposition();
                IEnumerable<Export> extensions;
    
                Container.TryGetExports(importDefinition, atomicComposition, out extensions);
    
                if (extensions != null && extensions.Count() > 0)
                {
                    var service = extensions.First().Value;
                    return PolicyInjection.Wrap(serviceContractType, service);
                }                
            }
            else
            {
                if (!type.IsMarshalByRef)
                {
                    throw new ArgumentException("Type Must inherit MarshalByRefObject if no ServiceInterface is Specified");
                }
                return PolicyInjection.Create(type);
            }
            return null;
        }
    
        public object GetInstance(InstanceContext instanceContext)
        {
            return GetInstance(instanceContext, null);
        }
    
        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
            var disposable = instance as IDisposable;
            if (disposable != null)
            {
                disposable.Dispose();
            }
            Container.Dispose();
        }
    
        #endregion
    
        #region Private Methods
    
        private void Compose()
        {
            var catalog = new AggregateCatalog();
            catalog.Catalogs.Add(new DirectoryCatalog(@".\")); //Extensions
            Container = new CompositionContainer(catalog);
        }
    
        #endregion
    }