1. Some business logic first
public interface ILogger
{
void Log(string information);
}
public class Logger : ILogger
{
public void Log(string information)
{
Console.WriteLine(information);
}
}
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DOB { get; set; }
public Guid ID { get; set; }
}
public interface IEmployeeService
{
[BeforeHandler]
[AfterHandler1]
[AfterHandler2]
bool AddOrUpdate(Employee employee);
[BeforeHandler]
[AfterHandler1]
[AfterHandler2]
Employee Get(Guid id);
[BeforeHandler]
[AfterHandler1]
[AfterHandler2]
bool Delete(Guid id);
}
public class EmployeeService : IEmployeeService
{
public EmployeeService(ILogger logger)
{
this.Logger = logger;
}
private ILogger Logger { get; set; }
#region IEmployeeService Members
public bool AddOrUpdate(Employee employee)
{
this.Logger.Log("AddOrUpdate called");
return true;
}
public Employee Get(Guid id)
{
this.Logger.Log("Get called");
return new Employee();
}
public bool Delete(Guid id)
{
this.Logger.Log("Delete called");
return true;
}
#endregion
}
2. Now Add some handlers/Matching rules
public class AlwaysMatchingRule : IMatchingRule
{
public bool Matches(System.Reflection.MethodBase member)
{
return true;
}
}
public class BeforeHandler : ICallHandler
{
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
Console.WriteLine("CallHandler '{0}' will now execute '{1}', Order '{2} ", this.GetType().Name, input.MethodBase.Name, this.Order);
return getNext().Invoke(input, getNext);
}
public int Order { get; set; }
}
public class AfterHandler1 : ICallHandler
{
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
var result = getNext().Invoke(input, getNext);
Console.WriteLine("CallHandler '{0}' executed '{1}', Order '{2}' ", this.GetType().Name, input.MethodBase.Name, this.Order);
return result;
}
public int Order { get; set; }
}
public class AfterHandler2 : ICallHandler
{
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
var result = getNext().Invoke(input, getNext);
Console.WriteLine("CallHandler '{0}' executed '{1}', Order '{2}' ", this.GetType().Name, input.MethodBase.Name, this.Order);
return result;
}
public int Order { get; set; }
}
public class BeforeHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container)
{
return new BeforeHandler();
}
}
public class AfterHandler1Attribute : HandlerAttribute
{
public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container)
{
return new AfterHandler1();
}
}
public class AfterHandler2Attribute : HandlerAttribute
{
public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container)
{
return new AfterHandler2();
}
}
3. Now configuring container
static void Main(string[] args)
{
//case 1: simple configuration
IUnityContainer container1 = new UnityContainer()
.RegisterType<ILogger, Logger>()
.RegisterType<IEmployeeService, EmployeeService>(new InjectionConstructor(typeof(ILogger)));
//case 2: Here ILogger will be resolved automatically, not need to inject
IUnityContainer container2 = new UnityContainer()
.RegisterType<ILogger, Logger>()
.RegisterType<IEmployeeService, EmployeeService>();
//case 3: Different way(obselete) of injection
IUnityContainer container3 = new UnityContainer()
.RegisterType<ILogger, Logger>()
.RegisterType<IEmployeeService, EmployeeService>()
.Configure<InjectedMembers>()
.ConfigureInjectionFor<EmployeeService>(
new InjectionConstructor(typeof(ILogger))).Container;
//case 4: Configuring with Policies->Rules->CallHandlers and
IUnityContainer container4 = new UnityContainer();
container4.AddNewExtension<Interception>();
container4
.Configure<Interception>()
.AddPolicy("Trace")
.AddMatchingRule("AlwaysMatchingRule")
.AddCallHandler("BeforeHandler")
.AddCallHandler("AfterHandler1")
.AddCallHandler("AfterHandler2").Interception.Container
.RegisterType<IMatchingRule, AlwaysMatchingRule>("AlwaysMatchingRule")
.RegisterType<ICallHandler, BeforeHandler>("BeforeHandler", new InjectionProperty("Order", 1))
.RegisterType<ICallHandler, AfterHandler1>("AfterHandler1", new InjectionProperty("Order", 2))
.RegisterType<ICallHandler, AfterHandler2>("AfterHandler2", new InjectionProperty("Order", 3))
.RegisterType<ILogger, Logger>()
.RegisterType<IEmployeeService, EmployeeService>()
.Configure<Interception>()
.SetInterceptorFor<IEmployeeService>(new TransparentProxyInterceptor());
//case 5: Using handler attributes - simplest of configuration
IUnityContainer container5 = new UnityContainer();
container5.AddNewExtension<Interception>();
container5
.Configure<Interception>()
.SetDefaultInterceptorFor<IEmployeeService>(new TransparentProxyInterceptor())
.Container
.RegisterType<ILogger, Logger>()
.RegisterType<IEmployeeService, EmployeeService>();
ExerciseAllServices(container1.Resolve<IEmployeeService>());
ExerciseAllServices(container2.Resolve<IEmployeeService>());
ExerciseAllServices(container3.Resolve<IEmployeeService>());
ExerciseAllServices(container4.Resolve<IEmployeeService>());
ExerciseAllServices(container5.Resolve<IEmployeeService>());
container1.Dispose();
container2.Dispose();
container3.Dispose();
container4.Dispose();
}
private static void ExerciseAllServices(IEmployeeService service)
{
service.AddOrUpdate(null);
service.Get(Guid.Empty);
service.Delete(Guid.Empty);
Console.WriteLine("-----------------------------------------------");
}
Some good References
http://blogsprajeesh.blogspot.in/2009/12/unity-application-block-interceptor.html
http://msdn.microsoft.com/en-us/library/ff660871%28v=pandp.20%29.aspx
http://msdn.microsoft.com/en-us/library/dd203208.aspx
http://msdn.microsoft.com/en-us/library/ff647107.aspx