Unity:将两个接口注册为一个具有拦截功能的单例 [英] Unity: Register two interfaces as one singleton with interception

查看:143
本文介绍了Unity:将两个接口注册为一个具有拦截功能的单例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个实现两个接口的类,并且想对类的方法应用拦截.

I have a class that implements two interfaces, and I want to apply interception to the class's methods.

我正在按照> Unity将两个接口注册为一个单例的建议,但结果令我感到惊讶.简而言之,似乎我的CallHandler被调用了两次.我拥有的最短的示例是:

I'm following the advice in Unity Register two interfaces as one singleton, but I'm surprised by the results. In a nutshell, it seems that my CallHandler is called twice. The shortest example I have is this:

public interface I1
{
    void Method1();
}

public interface I2
{
    void Method2();
}

public class C : I1, I2
{
    [Log]
    public void Method1() {}

    public void Method2() {}
}

public class LogAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new LogCallHandler();
    }
}

public class LogCallHandler : ICallHandler
{
    public IMethodReturn Invoke(
        IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        Console.WriteLine("Entering " + input.MethodBase.Name);
        var methodReturn = getNext().Invoke(input, getNext);
        Console.WriteLine("Leaving " + input.MethodBase.Name);
        return methodReturn;
    }

    public int Order { get; set; }
} 

void Test()
{
    IUnityContainer container = new UnityContainer();
    container.AddNewExtension<Interception>();
    container.RegisterType<C>(new ContainerControlledLifetimeManager());

    container.RegisterType<I1, C>(
        new Interceptor<TransparentProxyInterceptor>(),
        new InterceptionBehavior<PolicyInjectionBehavior>());

    container.RegisterType<I2, C>(
        new Interceptor<TransparentProxyInterceptor>(),
        new InterceptionBehavior<PolicyInjectionBehavior>());

    container.Resolve<I1>().Method1();
}

哪个给出以下输出:

Entering Method1
Entering Method1
Leaving Method1
Leaving Method1

删除"container.RegisterType I2,C"行可使日志仅出现一次.添加第三个接口I3(类似于I2)会使日志显示3次.

Removing the "container.RegisterType I2, C" line makes the log appear only once. Adding a third interface, I3, which is similar to I2, causes the log to appear three times.

我希望Log仅被调用一次.我可能可以通过让LogCallHandler检测是否正在从另一个LogCallHandler调用它来实现这一点,但这似乎不太好.

I would have expected the Log to be called only once. I can probably achieve this by having the LogCallHandler detect if it's being invoked from another LogCallHandler, but this seems inelegant.

最初我想将拦截行为应用于C,而不是分别应用于I1和I2,但这要求C从MarshalByRefObject继承,这是我尚不愿意施加的约束.

Originally I wanted to apply the interception behavior to C rather than to I1 and I2 separately, but this requires C to inherit from MarshalByRefObject which is a constraint I'm not yet willing to impose.

还有其他方法吗?

推荐答案

问题是您要将透明代理应用于每个接口.相反,如果将其应用于具体类,则只会获得一个代理.另外,除非您希望共享实例,否则无需将其设为单例.

The problem is that you are applying the transparent proxy to each interface. Instead, if you apply it to the concrete class you get only one proxy. Also, you don't need to make it a singleton unless you want the instance to be shared.

我在测试控制台项目中运行了此配置,并获得了预期的结果.包含一个能解决您的问题的有效代码片段,这是我的荣幸!

I ran this configuration in a test console project and got the desired result. Kudos for including a working snippet that isolated your problem!

var container = new UnityContainer()
    .AddNewExtension<Interception>()
    .RegisterType<I1, C>()
    .RegisterType<I2, C>()
    .RegisterType<C>(
        new ContainerControlledLifetimeManager(),
        new Interceptor<TransparentProxyInterceptor>(),
        new InterceptionBehavior<PolicyInjectionBehavior>()
    );

这篇关于Unity:将两个接口注册为一个具有拦截功能的单例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆