Registering WCF service in Unity Container
-
29-04-2021 - |
Question
I have a wcf service library that is hosted in a windows service. I need to intercept calls to Service methods. For this case it is suggested to register WCF into Unity container as can be seen in this link
http://weblogs.asp.net/fabio/archive/2009/03/24/inversion-of-control-with-wcf-and-unity.aspx
I am trying to implement a similar approach by Unity.WCF assembly from Codeplex.I could not understand where to put my container configuration or bootstrapper in wcf service library(or windows service). There is not a solid sample (vs solution) provided.
My Windows Service Host
private UnityServiceHost _serviceHost = null;
private readonly UnityContainer _container;
public Service() {
InitializeComponent();
_container = new UnityContainer();
_container.AddNewExtension<Interception>();
_container.RegisterType<ISecurityRepository, SecurityRepository>();
_container.Configure<Interception>().SetDefaultInterceptorFor<ISecurityRepository>(new TransparentProxyInterceptor());
}
protected override void OnStart(string[] args) {
//SecurityService
if (_serviceHost != null) {
_serviceHost.Close();
} else {
_serviceHost = new UnityServiceHost(_container, typeof(SecurityRepository));
_serviceHost.Open();
}
}
protected override void OnStop() {
//SecurityService
if (_serviceHost != null) {
_serviceHost.Close();
_serviceHost = null;
}
}
My Service Contract
[ServiceContract(SessionMode = SessionMode.Required)]
public interface ISecurityRepository
{
[OperationContract(IsInitiating = true)]
IList<vNavigationTree> GetNavigationTree(string ticket);
[OperationContract(IsInitiating = true)]
string GetSessionGuid(string userName, string IP, string machineName);
}
In this case it seems that interceptor does not work. Briefly what I need is a sample project in which the WCF Service is registered to DI container and the Service methods are intercepted.
Solution
I will try to explain what I tried to do more explicitly and how I managed to do it. I have a WPF application communicating with a database via WCF which means my app is divided roughly in two: client-side and server-side (WCF). I have wrapped the client-side into a Unity container via the UnityBootStrapper provided by PRISM. I need to wrap the server-side into another Unity container as well, in order to make Unity resolve the server-side dependencies.
My problem is solved by Unity.WCF (available as a Nuget package) which provides the UnityServiceHost class which can be used instead of ServiceHost. I guess this package is created in the way this post explains:
http://weblogs.asp.net/fabio/archive/2009/03/24/inversion-of-control-with-wcf-and-unity.aspx
OTHER TIPS
What you will need to do is take advantage of unity interception pipeline.
Unity provides a built-in policy injection behavior to facilitate the implementation of aop. The policy injection behavior attaches or injects some functionality to specific methods by using call handlers and matching rules on a per-method basis.
a. Start with a custom interface of a ICallhandler.
>> public interface ILogAttributeHandler : ICallHandler
>> {
>> }
>>
b. Add you implementation for your handler. This is the advice you want to apply when your method is intercepted.
>> public class ActivityAttributeHandler : ILogAttributeHandler
>> {
>> public ActivityAttributeHandler(string activityType)
>> {
>> ActivityType = activityType;
>> }
>> private string ActivityType { get; set; }
>> public int Order { get; set; }
>> public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
>> {
>> //// Invoke the handler
>> IMethodReturn output = getNext()(input, getNext);
>> //// Perform post-processing task
>> var agent = output.ReturnValue as Agent;
>> if (agent != null)
>> {
>> //// do work here
>> }
>> return getNext()(input, getNext);
>> }
}
c. Create your custom attribute, this will used as a pointcut in the program.
>> [AttributeUsage(AttributeTargets.Method)]
>> public class ActivityAttribute : HandlerAttribute
>> {
>> private readonly string _activityName;
>> public ActivityAttribute(string activityName)
>> {
>> _activityName = activityName;
>> }
>> }
>> public override ICallHandler CreateHandler(IUnityContainer container)
>> {
>> return null;
>>}
d. Now all you have left is to configure the interception within your unity configuration and add the attribute to your service interface operation that you want to be intercepted.
> container
> .RegisterType<ILogAttributeHandler, LogAttributeHandler>()
> .AddNewExtension<Interception>()
> .Configure<Interception>()
> .SetInterceptorFor<ISecurityRepository>("SecurityRepository", new
> InterfaceInterceptor());
e. Apply attributes to your interface operations
>>public interface ISecurityRepository
>> {
>> [OperationContract(IsInitiating = true)]
>> [Activity("Logon")]
>> IList<vNavigationTree> GetNavigationTree(string ticket)
>>}