Unity 拦截器如何确定调用是来自 WCF 还是来自内部服务?

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

我有一个与 Unity 拦截器挂钩的 WCF 服务,所有对 WCF 层的调用都被 Unity 拦截以用于审计目的。但是,Unity 似乎拦截了 ALL 调用来解析接口,无论调用是来自 WCF 还是内部。

考虑以下代码:

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

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

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

    public void DoStuff()
    {
    }
}

服务接口已通过拦截注册到 Unity:

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

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

当对 IMyService 进行 WCF 调用时,我触发了拦截器,这很好,我可以进行一些审计。然而,当解析 IMyService 时,拦截器再次触发,因为 IMyUtilityService 被注入到 IMyService 构造函数中。

有没有办法配置 Unity 来防止这种情况发生?或者拦截器内部有没有办法判断拦截是WCF直接触发的?还是需要创建不同的接口层来分离外部调用和内部调用?

最简单的方法可能是检查您是否收到 OperationContext

if (OperationContext.Current != null)
{
    // Called through WCF.
}
else
{
    // Not WCF.
}

并在拦截器中。

public class PipelineInterceptor : IInterceptionBehavior
{
    public bool WillExecute
    {
        get { return OperationContext.Current != null; }
    }

    // Other ...

}

我设法解决了在 Unity 中创造性地注册服务的问题。以前,服务在 Unity 中注册为仅内部服务或具有拦截功能的 WCF 服务。如果随后在内部使用 WCF 服务,拦截器就会出现问题。

注意:拦截器的问题可能是因为我们使用了 Lazy resolution of dependencies。

可以通过向Unity注册所有服务进行内部解析,然后使用显式名称注册WCF服务来解决该问题。当激活 WCF 端点时,可以使用显式名称解析实例。

例如注册服务:

container.RegisterType(interfaceType, implementationType);

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

然后在实例提供程序中创建实例:

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

首选解决方案,因为拦截器现在仅在调用 WCF 服务时注册和激活。