上善若水

水善利万物而不争
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

.NET | IOC Autofac

Posted on 2022-06-20 19:02  董锡振  阅读(90)  评论(0编辑  收藏  举报

 

先说下什么是IOC容器(Inversion of Control:控制反转)

传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试,

IOC是把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,指导我们如何设计出松耦合的程序。

这种应用本身不负责依赖对象的创建和维护,依赖对象的创建和维护是由外部容器负责的称为控制反转(IOC)。

 

 

 

using Autofac;

namespace AutofacTest
{
    public class Program
    {
        //Autofac是什么?
        //Autofac是一种IOC容器,那么什么是IOC容器呢? 
        //两个概念IOC(Inversion of Control,控制反转)和 DI(Dependency Injection,依赖注入):  
        //  IOC:调用者不再创建(不自己new)被调用者的实例,而是交给容器去创建(AutoFac就充当这里的容器),这就是控制反转。 
        //  DI: 容器创建好的实例再注入调用者的过程,就是依赖注入(比如:属性注入、构造函数注入等)。

        //  IOC就是一种软件设计思想,DI是这种软件设计思想的一个实现。
        //  IOC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。
        //  控制反转背后的核心思想是, 不再将类绑定在应用里, 而是反过来让类自己去new。
        //  传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试
        //  IOC是把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,指导我们如何设计出松耦合的程序。
        //  这种应用本身不负责依赖对象的创建和维护,依赖对象的创建和维护是由外部容器负责的称为控制反转(IOC)

        private static IContainer container { get; set; }
        //https://github.com/autofac/Autofac
        static void Main(string[] args)
        {
            //1.生成容器
            var builder = new ContainerBuilder();
            //2.注册组件(反射注册 n多注册方式中的一种)
            //https://www.processon.com/view/link/6072ed8863768912ae50b483#outline
            builder.RegisterType<Output>().As<IOutput>();
            builder.RegisterType<DateWriter>().As<IDateWriter>();
            //3.绑定
            container = builder.Build();
            //4.使用
            WriteToadyDate();
        }
        public static void WriteToadyDate()
        {
            //4.1 创建作用域,开始使用寿命范围,解析IDateWriter,使用,释放 
            using (var scope = container.BeginLifetimeScope())
            {
                //4.2 解析服务 请求需要的接口 容器会根据之前的RegisterType进行反转找到对应的类
                //    比如请求IDateWriter找到DateWriter
                var writer = scope.Resolve<IDateWriter>();
                writer.WriteToadyDate();
            }
        }

        //当你运行你的程序时… 
        //WriteDate方法要求Autofac提供IDateWriter.
        //Autofac发现IDateWriter映射到DateWriter所以创建了一个DateWriter对象
        //Autofac发现DateWriter构造函数需要IOutput
        //Autofac发现IOutput映射到Output,所以创建一个新的Output实例
        //Autofac使用Output实例完成DateWriter的创建
        //Autofac返回一个完整的DateWriter对象给”WriteToadyDate”来消费
        //最后,如果你希望你的应用输出一个不同的日期,你可以实现另外一个IDateWriter然后在app启动的时候改变一下注册过程  
    }

    // 这个接口帮助我们从Console类解耦"输出"方法 我们不需要关心怎样输出,只要知道能输出即可
    public interface IOutput
    {
        void Write(string content);
    }
    // 这里IOutput接口的实现完成向控制台的输出。 技术上讲,我们可以实现IOutput接口完成Debug或者Trace或者 其他的输出方式
    public class Output : IOutput
    {
        public void Write(string content)
        {
            Console.WriteLine(content);
        }
    }
    // 这个接口解耦实际输出日期的接口。 像IOutput一样,这个处理在后面的接口里抽象化
    public interface IDateWriter
    {
        void WriteToadyDate();
    }
    // DateWriter将上述两个接口进行组合 实现了WriteDate输出今天的日期   注意这里的构造函数参数是IOutput类型 
    public class DateWriter : IDateWriter
    {
        private IOutput _output;
        public DateWriter(IOutput output)
        {
            this._output = output;
        }
        public void WriteToadyDate()
        {
            this._output.Write(DateTime.Today.ToShortDateString());
        }
    }
}