2013-06-30 42 views
1

我有Unity設置來攔截方法調用,當方法用特定屬性修飾時。我希望所有的Unity代理對象在每個線程中保持不變(而不是暫時的)。從AttributeHandler訪問UnityContainer

問題是裝飾屬性創建的對象每次都創建爲「新」。我看不到從屬性內部訪問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; 
     } 
    } 
} 

回答

2

您可以在啓動過程中註冊使用Unity與PerThreadLifetimeManager您的調用句柄。

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

然後屬性可以從容器解決處理程序:

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

通常情況下,你不想容器的情況下,你的應用程序繞過,因爲這緊密結合所使用的特定容器。這將使用容器作爲Service Locator。許多人認爲這是一個anti-pattern

調用處理程序屬性是Unity基礎結構(用於您的應用程序)的一部分;它們擴展了Unity的摘要HandlerAttribute,並要求CreateHandler方法接受IUnityContainer,因此在HandlerAttribute中使用容器並非意外。

+0

這就是我一直在尋找的,謝謝。我對反模式很熟悉,但並不知道我可以用它作爲解決方案。 – flacnut