1

メソッドが特定の属性で装飾されている場合、メソッド呼び出しをインターセプトするように Unity をセットアップしています。すべての Unity プロキシ オブジェクトを (一時的ではなく) 各スレッド内で持続させたいと考えています。

問題は、装飾属性によって作成されたオブジェクトが毎回「新しく」作成されることです。属性内から UnityContainer にアクセスする方法がわかりません。可能であれば、LogHandler をスレッドごとのエンティティとして作成し、Unity 経由でリクエストします。(これは意味がありますか?ユニティを使用して、ユニティ インターセプトで使用されるオブジェクトを解決しますか?)。

このコードを実行すると、ロガーによるカウント出力は常に「1」になります。明確にするために、この「LogHandler」は私が永続化したいものです。

コードの他の場所で Unity を介してオブジェクトをどのように解決しますか? Unityコンテナを回しますか?コードのどこからでもリクエストできるパターンはありますか?

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>();
    }
}

通常、コンテナのインスタンスを渡すことは望ましくありません。これにより、アプリケーションが使用される特定のコンテナに密接に結合されるためです。これは、コンテナーをService Locatorとして使用します。多くの人はこれをアンチパターンだと考えています。

コール ハンドラの属性は、Unity インフラストラクチャの一部です (アプリケーション用)。それらは Unity の抽象を拡張HandlerAttributeし、IUnityContainer を受け入れるために CreateHandler メソッドを必要とするため、HandlerAttribute でコンテナーを使用することは予想外ではありません。

于 2013-06-30T15:10:31.540 に答える