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?
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
}