将自动 Autofac 与自动输出消息的动态代理一起使用

本文关键字:代理 一起 动态 消息 Autofac 输出 | 更新日期: 2023-09-27 18:23:48

public interface ILog
{
    void Write(string msg);
}
public class MyLog : ILog
{
    public void Write(string msg)
    {
        Console.WriteLine(msg);
    }
}
public interface ICanLog
{
    ILog Log { get; set; }
}
public interface IMyClass
{
    void Test();
}
public class MyClass : IMyClass, ICanLog
{
    public ILog Log { get; set; }
    public void Test()
    {
        Log.Write("Test");
    }
}

我正在使用带有Castle DynamicProxy的Autofac,并尝试让MyClass测试方法自动输出"开始"/"结束"。

public class MyLogInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("BEGIN");
        invocation.Proceed();
        Console.WriteLine("END");
    }
}

以下是测试代码:

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<MyLog>().As<ILog>();
builder.Register(c =>
{
    ProxyGenerator g = new ProxyGenerator();
    object proxy = g.CreateClassProxy(typeof(MyClass), new MyLogInterceptor());
    ICanLog proxyICanLog = (ICanLog)proxy;
    proxyICanLog.Log = c.Resolve<ILog>();
    return proxy;
}).As<IMyClass>();
using (var container = builder.Build())
{
    objectContext.Container = container;
    IMyClass myclass = container.Resolve<IMyClass>();
    myclass.Test();
}

但是结果没有输出"开始"/"结束",为什么?

如果我创建自动日志模块,尝试自动构建日志属性实例

    public class AutoLogModule : Autofac.Module
{
    protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
    {
        var type = registration.Activator.LimitType;
        if (HasPropertyDependencyOnClass(type))
        {
            registration.Activated += InjectClassViaProperty;
        }
    }
    private bool HasPropertyDependencyOnClass(Type type)
    {
        return type.GetProperties().Any(property => property.CanWrite && property.PropertyType==typeof(ILog));
    }
    private void InjectClassViaProperty(object sender, ActivatedEventArgs<object> evt)
    {
        var type = evt.Instance.GetType();
        var propertyInfo = type.GetProperties().First(x => x.CanWrite && x.PropertyType==typeof(ILog));
        ILog log = new MyLog();
        propertyInfo.SetValue(evt.Instance, log, null);
    }
}

以下是测试代码:

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<MyLog>().As<ILog>();
builder.RegisterModule(new AutoLogModule());
builder.Register(c =>
{
    ProxyGenerator g = new ProxyGenerator();
    object proxy = g.CreateClassProxy(typeof(MyClass), new MyLogInterceptor());
    //ICanLog proxyICanLog = (ICanLog)proxy;
    //proxyICanLog.Log = c.Resolve<ILog>();
    return proxy;
}).As<IMyClass>();
using (var container = builder.Build())
{
    objectContext.Container = container;
    IMyClass myclass = container.Resolve<IMyClass>();
    myclass.Test();
}

结果是测试方法抛出"对象引用未设置为对象的实例。"in Log.Write("Test"(

这个功能怎么写?

将自动 Autofac 与自动输出消息的动态代理一起使用

我知道

这是一个相当古老的帖子,但是当我试图用Autofac完成同样的事情时,我找到了帮助我实现它的文档。我会回答以防万一它对其他人有帮助。

就我而言,我正在使用Autofac 4.92和名为Autofac.Extras.DynamicProxy 4.5.0的DynamicProxy的额外软件包,因为文档是有用的。

我看到您注册Interceptors的地方有所不同.即使你正在做的事情是我最初会做的事情;不是 Autofac 文档目前关于如何注册拦截器的说法:

 builder.RegisterType<MyClass>().As<IMyClass>().EnableInterfaceInterceptors();
// Typed registration
builder.Register(c => new MyLogInterceptor ();

最后,您需要将拦截器与要拦截的类型相关联:

[Intercept(typeof(MyLogInterceptor))]
public class MyClass : IMyClass, ICanLog
{
    public ILog Log { get; set; }
    public void Test()
    {
       Log.Write("Test");
    }
}

我希望这个答案可能会有所帮助。无论如何,Autofac 文档逐步解释了如何做到这一点,以防我的代码可能错误地跳过一些相关部分。