Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Logging 尝试使用DynamicProxy为StructureMap创建日志侦听器_Logging_Structuremap_Castle Dynamicproxy - Fatal编程技术网

Logging 尝试使用DynamicProxy为StructureMap创建日志侦听器

Logging 尝试使用DynamicProxy为StructureMap创建日志侦听器,logging,structuremap,castle-dynamicproxy,Logging,Structuremap,Castle Dynamicproxy,我正在尝试记录从UI(DNN模块)到它使用的一些不同服务的调用,以了解人们是如何与站点交互的。我正在使用StructureMap 2.5.3.0和Log4Net 我在单独的类/实例对上工作得很好,但我必须这样配置: ObjectFactory.Configure(ce => ce.ForRequestedType<IRegService>() .TheDefaultIsConcreteType<RegService>()

我正在尝试记录从UI(DNN模块)到它使用的一些不同服务的调用,以了解人们是如何与站点交互的。我正在使用StructureMap 2.5.3.0和Log4Net

我在单独的类/实例对上工作得很好,但我必须这样配置:

ObjectFactory.Configure(ce =>
        ce.ForRequestedType<IRegService>()
          .TheDefaultIsConcreteType<RegService>()
          .EnrichWith(LoggingEnrichment.InterfaceLogger<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());
    }
}
这是可行的,但有几个问题:

  • 我必须手动配置每个服务接口对
  • 我只想在从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
    给了我一个类,这个类没有实现构建上下文定义的接口。这导致必须将
    接口记录器的实现更改为

        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;
        }
    
    返回接口proxy上的断点从未到达,这表示
    context.BuildStack.Current.RequestedType
    未返回正确的接口。奇怪的是,我所有的类似乎都被正确注入

    此外,即使这是工作,我仍然有一个问题,就是只想拦截来自UI层的调用


    我正在寻找解决前两个问题的方法,以及我使用
    TypeInterceptor

    的错误之处。我使用约定解决了这个问题。以下是我为实现这一目标所采取的步骤

    首先,我对指定的程序集进行了扫描,我将在其中附加装饰程序

    x.Scan(scanner =>
                    {
                        scanner.Assembly("MyProject.Services"); // Specific assemblyname
                        scanner.Convention<ServiceRegistrationConvention>();
                        scanner.WithDefaultConventions();
                        scanner.LookForRegistries();
    
                    });
    
    我使用与您相同的LoggingEnrichment类


    希望这能解决您提到的问题。

    您好,遇到了同样的问题。你解决了这个问题吗?嗨,我下面的答案解决了你的问题吗?Tnx。
     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));
                }
    
            }
        }