• Autofac 学习简易教程随笔(一)


    概念

            Autofac 是一款超赞的.NET IoC 容器 . 它管理类之间的依赖关系, 从而使 应用在规模及复杂性增长的情况下依然可以轻易地修改

            那么,什么是IoC(控制反转),以及IoC和DI(依赖注入),已经有大神对这个解释的非常清楚,感兴趣的可以看这个帖:https://www.iteye.com/blog/jinnianshilongnian-1413846

            本着多动原则,我这里直接进入step by step环节。本人也建议先按步骤做一遍简单的Autofac Demo项目,然后再看大神对IoC和DI介绍的帖子,会更容易理解。

    实践

    1、创建一个控制台项目,如下图:

    2、引入autofac nuget包,如下图:

    3、创建接口IVehicle(交通工具接口)、类Bus(巴士,实现IVehicle接口),代码如下:

        IVehicle.cs:

    /// <summary>
        /// 交通工具接口
        /// </summary>
        public interface IVehicle
        {
            /// <summary>
            /// 去哪里
            /// </summary>
            /// <param name="targetAddress">目的地</param>
            void GoTo(string targetAddress);
        }
    View Code

        Bus.cs:

    /// <summary>
        /// 大巴
        /// </summary>
        public class Bus : IVehicle, IDisposable
        {
            private string _vehicleName { get; }
    
            public Bus()
            {
                _vehicleName = "大巴";
            }
    
            public void GoTo(string targetAddress)
            {
                Console.WriteLine($"乘 {_vehicleName} 去 {targetAddress}");
            }
    
            public void Dispose()
            {
                Console.WriteLine($"{nameof(Bus)} dispose");
            }
        }
    View Code

    4、创建接口IPassenger(乘客/旅客接口)、类Student(学生,实现IPassenger接口),代码如下:

        IPassenger:

    /// <summary>
        /// 乘客/旅客接口
        /// </summary>
        public interface IPassenger
        {
            /// <summary>
            /// 乘坐交通工具去{targetAddr}(目的地)
            /// </summary>
            /// <param name="targetAddr">目的地</param>
            void ByVehicleTo(string targetAddr);
        }
    View Code

       Student:

    /// <summary>
        /// 学生旅客 实现了乘客/旅客接口
        /// </summary>
        public class Student : IPassenger
        {
            private readonly IVehicle _vehicle;
    
            /// <summary>
            /// 构造方法
            /// </summary>
            /// <param name="vehicle">交通工具</param>
            public Student(IVehicle vehicle)
            {
                _vehicle = vehicle;
            }
    
            /// <summary>
            /// 乘坐交通工具去{targetAddr}(目的地)
            /// </summary>
            /// <param name="targetAddr"></param>
            public void ByVehicleTo(string targetAddr)
            {
                Console.WriteLine("学生旅客:");
    
                _vehicle.GoTo(targetAddr);
            }
        }
    View Code

    5、修改Program.cs的代码,如下:

    class Program
        {
            private static IContainer Container { get; set; }
    
            static void Main(string[] args)
            {
                var builder = new ContainerBuilder();
                builder.RegisterType<Bus>().As<IVehicle>();
                //builder.RegisterType<Train>().As<IVehicle>();
                builder.RegisterType<Student>().As<IPassenger>();
                Container = builder.Build();
    
                Travel();
    
                Console.ReadLine();
            }
    
    
            public static void Travel()
            {
                using (var scope = Container.BeginLifetimeScope())
                {
                    var passenger = scope.Resolve<IPassenger>();
                    passenger.ByVehicleTo("Beijing");
                }
            }
        }
    View Code

    直接运行程序,得到结果如下:

    代码解读

            回顾一下上面的代码,我们定义了两个接口:IPassenger(乘客/旅客接口)和IVehicle(交通工具接口),并且分别定义了Student(学生类)实现了IPassenger接口,以及Bus(巴士类)实现了IVehicle接口。

            但是,在Program.cs的代码中,我们并没用任何调用new直接生成Student或Bus对象的代码,下面我们看一下Main方法的代码注释,了解一下IoC容器简单的使用方法:

    //以下代码是初始化容器并且注册程序中需要使用到的类型为组件
    
    //实例化一个Autofac.ContainerBuilder对象
    var builder = new ContainerBuilder();
    
    //将Bus类型注册为组件,并暴露接口IVehicle作为服务。
    builder.RegisterType<Bus>().As<IVehicle>();
    
    //将Student类型注册为组件,并暴露接口IPassenger作为服务。
    builder.RegisterType<Student>().As<IPassenger>();
    
    //构建容器
    Container = builder.Build();
    

      

      在看看Travel()方法中的代码:

    public static void Travel(){
        //创建了一个生命周期范围(scope), 从中可以解析依赖项
        using (var scope = Container.BeginLifetimeScope())
        {
            //从生命周期范围(scope)中解析IPassenger,
            //Autofac发现IPassenger对应Student,因此开始创建Student
            //Autofac发现Student的构造方法需要一个IVehicle(这就是“构造方法注入”)
            //Autofac发现IVehicle对应Bus,因此开始创建新的Bus实例
            //Autofac使用新的Bus实例完成Student的创建
            //Autofac返回完整构建的 Student 给"Travel"方法使用
            var passenger = scope.Resolve<IPassenger>();
    
            //调用 passenger.ByVehicleTo("Beijing") 就是一个全新的 passenger.ByVehicleTo("Beijing") 因为这是在生命周期中解析出的
            passenger.ByVehicleTo("Beijing");
    
            //Autofac生命周期被释放. 任何从生命周期解析出的可释放对象也都被同时释放。
            //例如这里的Bus实现了IDisposable接口,在scope生命周期被释放的同时会调用Bus的Dispose。
        }
    }
    

      

          如果后面需要增加一个交通工具,例如:Train(火车),同样实现接口IVehicle,代码如下:

    public class Train : IVehicle
    {
        public void GoTo(string targetAddress)
        {
            Console.WriteLine($"乘坐火车去 {targetAddress}");
        }
    }
    View Code

          然后只需修改Program.cs中Main方法内的IoC容器注册组件部分代码,如下:

    static void Main(string[] args)
    {
        var builder = new ContainerBuilder();
        //builder.RegisterType<Bus>().As<IVehicle>(); //这行代码注释掉
        builder.RegisterType<Train>().As<IVehicle>(); //加上这行代码
        builder.RegisterType<Student>().As<IPassenger>();
        Container = builder.Build();
    
        Travel();
    
        Console.ReadLine();
    }
    

      然后运行程序,得出以下结果:

          Travel()方法里面的代码我们一点都没改,只是将IVehicle服务的对应组件注册类型修改为Train,结果就变成使用Train类的实例化运行了。这个就是IoC“控制反转”,也叫DI“依赖注入”。

    源代码:https://github.com/LuckyDonkey/DotNet_Some_Samples/tree/master/IoC.DI.Autofac.Demos/IoC.DI.Autofac.FirstDemo

    参考:https://autofaccn.readthedocs.io/zh/latest/getting-started/index.html

        

  • 相关阅读:
    CAD2014启动出现loadlibrary failed with error 87
    MFC界面更新实现方法
    easyui tabs update后tab上关闭图标失效的解决方案
    SQLServer
    Socket异步存储示例
    AspNetPager控件分页使用方法
    sqlserver 2008 孤立用户解决方法
    NPOI 2.0 读取、编辑、保存Excel文件
    NPOI 2.0 创建Excel文件
    jQuery.extend 函数详解
  • 原文地址:https://www.cnblogs.com/lucky-donkey/p/13592420.html
Copyright © 2020-2023  润新知