1

当方法用特定属性修饰时,我有 Unity 设置来拦截方法调用。我希望所有 Unity 代理对象都保留在每个线程中(而不是暂时的)。

问题是装饰属性创建的对象每次都是“新”创建的。我看不到从属性中访问 UnityContainer 的方法。如果可以的话,我会将 LogHandler 创建为每个线程实体并通过 Unity 请求它。(这甚至有意义吗?使用 Unity 来解析用于统一拦截的对象?)。

如果您运行此代码,则记录器输出的计数始终为“1”。需要明确的是,这个“LogHandler”是我想要坚持的。

您如何通过代码中其他地方的统一来解析对象?你绕过统一容器吗?有没有一种模式可以用来从我的代码中的任何地方请求它?

using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;

namespace UnityTest2
{
    class Program
    {
        private static UnityContainer _uC;

        static void Main(string[] args)
        {
            _uC = new UnityContainer();
            _uC.AddNewExtension<Interception>();

            _uC.Configure<Interception>().SetInterceptorFor<ICalc>(new InterfaceInterceptor());
            _uC.RegisterType<ICalc, Calc>( new PerThreadLifetimeManager() );
            var c = _uC.Resolve<ICalc>();
            Console.WriteLine(c.Add(3, 7));
            Console.WriteLine(c.Sub(3, 7));
            Console.ReadKey();
        }
    }

    public class LogAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            // I want this to persist per thread
            return new LogHandler();
        }
    }

    public class LogHandler : ICallHandler
    {
        private int runCount = 0;
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {

            runCount++;

            // this is always '1'
            Console.WriteLine(runCount);
            return getNext()(input, getNext);
        }

        public int Order { get; set; }
    }

    public interface ICalc
    {
        int Add(int x, int y);
        int Sub(int x, int y);
        int Mul(int x, int y);
    }

    public class Calc : ICalc
    {
        [Log]
        public int Add(int x, int y)
        {
            return x + y;
        }
        [Log]
        public int Sub(int x, int y)
        {
            return x - y;
        }

        public int Mul(int x, int y)
        {
            return x * y;
        }
    }
}
4

1 回答 1

2

您可以在启动期间使用 PerThreadLifetimeManager 向 Unity 注册您的调用处理程序。

_uC.RegisterType<LoggingCallHandler>(new PerThreadLifetimeManager());

然后该属性可以从容器中解析处理程序:

public class LoggingAttribute : HandlerAttribute
{        
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return container.Resolve<LoggingCallHandler>();
    }
}

通常,您不想传递容器的实例,因为这会将您的应用程序与使用的特定容器紧密耦合。这将使用容器作为服务定位器。许多人认为这是一种反模式

调用处理程序属性是 Unity 基础架构的一部分(适用于您的应用程序);它们扩展了 Unity 的抽象HandlerAttribute并要求 CreateHandler 方法接受 IUnityContainer,因此在 HandlerAttribute 中使用容器并不意外。

于 2013-06-30T15:10:31.540 回答