gpt4 book ai didi

logging - 尝试使用 DynamicProxy 为 StructureMap 制作日志拦截器

转载 作者:行者123 更新时间:2023-12-01 05:42:02 24 4
gpt4 key购买 nike

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

我在单个类/实例对上运行良好,但我必须配置如下:

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

这可行,但有几个问题:
  • 我必须手动配置每个服务 <-> 接口(interface)对
  • 我只想在从 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正在给我一个不实现由构建上下文定义的接口(interface)的类。这导致不得不更改 InterfaceLogger 的实现。到
        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;
    }
    return interfaceProxy; 上的断点从未达到,这表明 context.BuildStack.Current.RequestedType没有返回正确的界面。奇怪的是,我所有的类(class)似乎都被正确注入(inject)了。

    此外,即使这有效,我仍然会遇到只想拦截来自 UI 层的调用的问题。

    我正在寻找我的前 2 个问题的方法,以及我在 TypeInterceptor 上做错了什么

    最佳答案

    我通过使用约定解决了这个问题。以下是我为实现这一目标所做的步骤。

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

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

    });

    然后我创建了一个 Convention 类。我实际上是从这个线程得到的 Decorating a generic interface with Structuremap并根据您的实现进行了一些修改。

    最后这是 Convention 类。
     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 类。

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

    关于logging - 尝试使用 DynamicProxy 为 StructureMap 制作日志拦截器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4922278/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com