1
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 Test Method 出力 "BEGIN"/"END" を自動化しようとしています。

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

しかし、結果として "BEGIN"/"END" が出力されないのはなぜですか?

ログプロパティインスタンスを自動で構築しようとするAutoLogModuleを作成した場合

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

結果は、Test Method throw "Object reference not set to an instance of an object." です。Log.Write("Test") で

この機能の書き方

4

1 に答える 1