2011-02-07 4 views
4

사람들이 사이트와 상호 작용하는 방식을 프로파일 링하기 위해 UI (DNN 모듈)의 호출을 사용하는 다양한 서비스로 로깅하려고합니다. 내가 StructureMap 2.5.3.0 및 Log4NetDynamicProxy를 사용하여 StructureMap에 대한 로깅 인터셉터를 만들려고합니다.

을 사용하고

나는 각각의 클래스/인스턴스 쌍 잘 작동 것들,하지만이 같은 것들을 구성해야에게있어 :

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

IRegService 두 번 조금 지저분한 느낌 데 , 나는 그걸로 살 수있다.

로깅은 다음과 같이 구현됩니다

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 레이어에서 호출을 가로 채기를 원할뿐입니다.

나는 방법을 처음이 문제를 찾고 있어요, 그리고 내가 규칙을 사용하여이 주변에있어 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 클래스를 사용합니다.

호프가이 문제를 해결하기를 바랍니다.

관련 문제