2011-02-07 3 views
4

UI(DNNモジュール)からの呼び出しを、さまざまなサービスのログに記録しようとしています。DynamicProxyを使用してStructureMapのログインターセプタを作成しようとしています

ObjectFactory.Configure(ce => 
     ce.ForRequestedType<IRegService>() 
      .TheDefaultIsConcreteType<RegService>() 
      .EnrichWith(LoggingEnrichment.InterfaceLogger<IRegService>)); 

IRegServiceが二度少し厄介に感じ持って:私は、私は物事は、個々のクラス/インスタンスのペアにうまく機能してしまったが、私はこのようなものを設定する必要がありますのStructureMap 2.5.3.0とlog4netの

を使用していますしかし、私はそれで生きることができます。

ログは次のように実装されています

public class LoggingEnrichment 
{ 
    public static object InterfaceLogger<TInterface>(object concrete) 
    { 
     return InterfaceLogger(typeof(TInterface), concrete); 
    } 

    public static object InterfaceLogger(Type iinterface, object concrete) 
    { 
     var dynamicProxy = new ProxyGenerator(); 
     return dynamicProxy.CreateInterfaceProxyWithTarget(iinterface, concrete, new LogInterceptor()); 
    } 
} 

public class LogInterceptor : IInterceptor 
{ 
    public void Intercept(IInvocation invocation) 
    { 
     var watch = new Stopwatch(); 
     watch.Start(); 
     invocation.Proceed(); 
     watch.Stop(); 
     ILog logger = LogManager.GetLogger(typeof(LogInterceptor)); 
     var sb = new StringBuilder(); 
     sb.AppendFormat("Calling: {0}.{1}\n", invocation.InvocationTarget.GetType(), invocation.MethodInvocationTarget.Name); 
     var param = invocation.Method.GetParameters(); 
     if (param.Length > 0) sb.Append("With:\n"); 
     for (int i = 0; i < param.Length; i++) 
     { 
      sb.AppendFormat("\t{0}\n\t\t{1}", param[i].Name, invocation.GetArgumentValue(i)); 
     } 
     if(invocation.Method.ReturnType != typeof(void)) 
     { 
      sb.AppendFormat("Returning: {0}\n", invocation.ReturnValue ?? "null"); 
     } 
     sb.AppendFormat("In: {0}ms\n", watch.ElapsedMilliseconds); 
     logger.Debug(sb.ToString()); 
    } 
} 

これは動作しますが、夫婦の問題があります:私は手動で各サービス<設定する必要が

  1. - のみ>インターフェイスペア
  2. IをUIからサービスが呼び出されたときのログを取り消したい場合

私はのStructureMapのためTypeInterceptorを実装することによって、これを回避しようとした:

public class ApplicationRegistry : Registry 
{ 
    public ApplicationRegistry() 
    { 
     RegisterInterceptor(new LoggingInterceptor()); 
     Scan(scanner => 
     { 
      scanner.TheCallingAssembly(); 
      var codeBase = System.Reflection.Assembly.GetExecutingAssembly().CodeBase.Replace("file:///", String.Empty); 
      codeBase = codeBase.Substring(0, codeBase.LastIndexOf("/")); 
      scanner.AssembliesFromPath(codeBase); 
      scanner.WithDefaultConventions(); 
      scanner.LookForRegistries(); 
     }); 
    } 
} 

public class LoggingInterceptor :TypeInterceptor 
{ 
    public object Process(object target, IContext context) 
    { 
     var newTarget = target; 
     if (context.BuildStack.Current != null && context.BuildStack.Current.RequestedType != null) 
     { 
      newTarget = LoggingEnrichment.InterfaceLogger(context.BuildStack.Current.RequestedType, target); 
     } 
     return newTarget; 
    } 

    public bool MatchesType(Type type) 
    { 
     return type.Name.EndsWith("Service", StringComparison.OrdinalIgnoreCase); 
    } 
} 

しかし、私はProcessへの呼び出しは私によって定義されたインタフェースを実装していないクラスを与えていることに問題があることを取得していますコンテキストを構築する。これはreturn interfaceProxy;上のブレークポイントに到達されることはありません

public static object InterfaceLogger(Type iinterface, object concrete) 
    { 
     if(!iinterface.IsAssignableFrom(concrete.GetType())) return concrete; 
     var dynamicProxy = new ProxyGenerator(); 
     var interfaceProxy = dynamicProxy.CreateInterfaceProxyWithTarget(iinterface, concrete, new LogInterceptor()); 
     return interfaceProxy; 
    } 

InterfaceLoggerの実装を変更することになりました、これはcontext.BuildStack.Current.RequestedTypeは、右のインターフェイスを返していないことを示します。奇妙なことは、すべてのクラスが正しく注入されているようです。

また、これが動作していても、UIレイヤーからの呼び出しを傍受したいという問題が残っています。

私は道のために私の最初の2つの問題を探しています、と私は条約を使って、これを周りましたTypeInterceptor

+0

こんにちは、同じ問題に遭遇しました。これを解決しましたか? Tnx。 – daxsorbito

+0

こんにちは、私の答えはあなたの問題を解決しましたか? Tnx。 – daxsorbito

答えて

1

と間違ってやっても何を。以下は私がこれを達成するためにしたステップです。

まず、指定したアセンブリで私のデコレータを添付してスキャンを行いました。

x.Scan(scanner => 
       { 
        scanner.Assembly("MyProject.Services"); // Specific assemblyname 
        scanner.Convention<ServiceRegistrationConvention>(); 
        scanner.WithDefaultConventions(); 
        scanner.LookForRegistries(); 

       }); 

次に、コンベンションクラスを作成しました。私は実際にこのスレッドDecorating a generic interface with Structuremapから取得し、あなたの実装に基づいていくつかのリビジョンを出しました。

最後に、これがコンベンションクラスです。

public class ServiceRegistrationConvention : IRegistrationConvention 
    { 
     public void Process(Type type, Registry registry) 
     { 
      var handlerInterfaces = (from t in type.GetInterfaces() 
            where 
             (t.Namespace.StartsWith("MyProject.UIServices", StringComparison.OrdinalIgnoreCase) 
             || t.Namespace.StartsWith("MyProject.Services", StringComparison.OrdinalIgnoreCase)) 
            select t); 


      foreach (var handler in handlerInterfaces) 
      { 
       registry.For(handler) 
        .EnrichWith((ctx, orig) => LoggingEnrichment.InterfaceLogger(handler, orig)); 
      } 

     } 
    } 

私は同じLoggingEnrichmentクラスを使用しています。

これはあなたの言及された問題を解決します。

関連する問題