Search code examples
c#wcfunity-containerunity-interception

How can the Unity interceptor determine if a call originated from WCF or from an internal service?


I have a WCF service hooked with a Unity interceptor and all calls to the WCF layer is intercepted by Unity for auditing purposes. However, Unity seems to intercept ALL calls to resolve the interface, whether the call originated from WCF or internally.

Consider the following code:

[ServiceContract]
public interface IMyUtilityService
{
    [OperationContract]
    void DoUtilityStuff();
}

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    void DoStuff();
}

class MyService : IMyService
{
    public MyService(IMyUtilityService myUtilityService)
    {
    }

    public void DoStuff()
    {
    }
}

The service interfaces are registered with Unity with interception:

container.RegisterType<IMyUtilityService, MyUtilityService>(
    new Interceptor<InterfaceInterceptor>(), 
    new InterceptionBehavior<PipelineInterceptor>());

container.RegisterType<IMyService, MyService>(
    new Interceptor<InterfaceInterceptor>(), 
    new InterceptionBehavior<PipelineInterceptor>());

When a WCF call is made to IMyService I get the interceptor firing which is great and I can do some auditing. When IMyService is resolved, however, the interceptor triggers again as IMyUtilityService is injected into the IMyService constructor.

Is there a way to configure Unity to prevent this? Or is there a way inside the interceptor to determine that the interception was directly triggered by WCF? Or do I need to create a different interface layer to separate the external calls and the internal calls?


Solution

  • I managed to solve the issue with creative registration of services in Unity. Previously a service was registered with Unity as either an internal only service or as a WCF service with interception. If the WCF service is then used internally problems ensued with the interceptor.

    Note: the problem with the interceptor may have been because we used Lazy resolution of dependencies.

    The problem can be solved by registering all services with Unity for internal resolution and then registering WCF services with explicit names. When the WCF endpoint is activated the instance can be resolved using the explicit name.

    For instance, registering the service:

    container.RegisterType(interfaceType, implementationType);
    
    if (isWCF)
        container.RegisterType(
            interfaceType, 
            implementationType, 
            "WCF", // name for resolving WCF services
            new Interceptor<InterfaceInterceptor>(), 
            new InterceptionBehaviour<PipelineInterceptor>());
    

    And then creating the instance in the Instance Provider:

    public object GetInstance(InstanceContext instanceContext, Message message)
    {
        return _container.Resolve(_interfaceType, "WCF");
    }
    

    Solution is preferred as the interceptor is now only registered and activated against invocation of the WCF services.