【问题标题】:Autofac constructor chainingAutofac 构造函数链接
【发布时间】:2015-06-12 17:14:14
【问题描述】:

我将如何使用 Autofac 实现等效输出123

我查看了以下内容,但我认为它不太符合我想要实现的目标。

http://docs.autofac.org/en/latest/advanced/adapters-decorators.html

也许有人可以启发我 - 这是 decorator 吗?

using System;

namespace Prototypes.Decorator
{
    public class Program
    {
        static void Main()
        {
            new Class1(new Class2(new Class3(null))).Do();

            Console.ReadKey(true);
        }
    }

    public interface ICommand
    {
        void Do();
    }

    public abstract class BaseClass : ICommand
    {
        private readonly ICommand _command;

        protected BaseClass(ICommand command)
        {
            _command = command;
        }

        public abstract void Do();

        public void CallNext()
        {
            if (_command != null)
            {
                _command.Do();
            }
        }
    }

    public class Class1 : BaseClass
    {
        public Class1(ICommand command) : base(command)
        {
        }

        public override void Do()
        {
            Console.Write(1);

            CallNext();
        }
    }

    public class Class2 : BaseClass
    {
        public Class2(ICommand command) : base(command)
        {
        }

        public override void Do()
        {
            Console.Write(2);

            CallNext();
        }
    }

    public class Class3 : BaseClass
    {
        public Class3(ICommand command) : base(command)
        {
        }

        public override void Do()
        {
            Console.Write(3);

            CallNext();
        }
    }
}

如果基础构造函数上还有另一个接口,那该怎么办?像protected BaseClass(ICommand command, ILog log) { ... }这样似是而非的东西

【问题讨论】:

    标签: c# inversion-of-control decorator autofac


    【解决方案1】:

    有几种方法可以构建您的容器以实现您的需求,您可以使用键控服务或 lambdas。

    与使用字符串相比,Lambda 更不容易出错,所以这里有一个简单的容器注册,可以满足您的需要:

    ContainerBuilder cbLambdas = new ContainerBuilder();
    cbLambdas.Register<Class3>(ctx => new Class3(null));
    cbLambdas.Register<Class2>(ctx => new Class2(ctx.Resolve<Class3>()));
    cbLambdas.Register<Class1>(ctx => new Class1(ctx.Resolve<Class2>()));
    
    IContainer containerLambda = cbLambdas.Build();
    containerLambda.Resolve<Class1>().Do();
    

    如果添加 ILog 接口,按照如下声明:

    public interface ILog
    {
        void Log();
    }
    
    public class NullLog : ILog
    {
        public void Log() { }
    }
    

    并将其添加为依赖项(在这种情况下仅适用于 Class2)

    public class Class1 : BaseClass
    {
        private readonly ILog logger;
    
        public Class1(ICommand command, ILog logger)
            : base(command)
        {
            this.logger = logger;
        }
    
        public override void Do()
        {
            Console.Write(1);
            CallNext();
        }
    }
    

    那么你的注册就变成了:

    ContainerBuilder cbWithLog = new ContainerBuilder();
    cbWithLog.RegisterType<NullLog>().As<ILog>();
    cbWithLog.Register<Class3>(ctx => new Class3(null));
    cbWithLog.Register<Class2>(ctx => new Class2(ctx.Resolve<Class3>()));
    cbWithLog.Register<Class1>(ctx => new Class1(ctx.Resolve<Class2>(), ctx.Resolve<ILog>()));
    
    IContainer containerLog = cbWithLog.Build();
    containerLog.Resolve<Class1>().Do();
    

    【讨论】:

    • 看起来很简单。一旦我早上试一试,就会标记为正确。
    • 传奇,完美运行!我所做的唯一更改是注册Class3As&lt;ICommand&gt;()。非常感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-24
    • 1970-01-01
    • 2011-11-26
    • 1970-01-01
    相关资源
    最近更新 更多