Silentdoer

导航

用Rider写一个有IOC容器Autofac的.net core的程序

一:Autofac是一个和Java里的Spring IOC容器一样的东西,不过它确实没有Spring里的那么方便,主要是在于它没有提供足够的Api和扫描方式等等,不过优点是它比Spring要快很多,而且Spring里的通过注解注入、自动装配、Aop等等通过自己写一定的代码也是可以实现的;

二:这里只先做一个最简单的Autofac的演示,我这里用的是Jetbrains的Rider,说实在话如果VS和Rider在没有配置的前提下个人还是觉得Rider好用,特别是一些快捷输入和源码查看比VS好用的多;

2.1.打开Rider,然后新建一个空的解决方案叫AutofacSolution1;

2.2.然后在此之上Add一个Project,选择.Net Core区域里的Console Application,如叫ConsoleApp1【注意C#实际编程里主入口的Project尽量精简,好能更好的设计出灵活的热部署应用】。

2.3.通过Tools里的Nuget安装Autofac到这个Project里来,然后在Dependency里(VS里对应的是References)的Packages里就是我们通过Nuget安装的依赖;

接下来就直接上代码了,一些用法和解释也直接在代码里:

class Program
    {
        
        public string Name { get; set; }
        
        static void Main(string[] args)
        {
            // builder一般只是用来注册Bean的描述信息的(转java蛮久了,习惯了用bean称呼一些特定领域的对象),
            var builder = new ContainerBuilder();
            // 注意,这里是注册了一个对象【也可以只注册类型builder.RegisterType()】,然后还同时给这个对象进行一个熟悉的装配,这里要注意Resolve如果找不到bean是会报错的
            // 如果不确定一定有可以用TryResolve,后面的AsSelf()表示将这个bean的类型以自己的类型为准,还可以通过.AsImplementedInterfaces()来表示Resolve时可以通过其接口来Resolve到bean
            // 后面还可以用.PropertiesAutowired()表示对Program类的这个bean做一个所有public set属性的自动装配,不过我们这里手动去做了部分的自动装配就不加这个了;
            // 这里还可以设置生命周期,比如某个bean是单例的还是原型的还是基于线程的,还可以register一个Module还实现bean的分开注册(Module对象不会注册,它只起一个桥梁作用)
            builder.Register(c => new Program(){Name = c.Resolve<string>()}).AsSelf();
           
            // 还可以给builder添加监听器,比如可以监听IComponentRegistration配置完成的时候产生的事件,从而可以自定义的对它们做一些调整,类似Spring里的BeanPostProcessor之类的
            builder.RegisterInstance("数据里防静电").Keyed<string>("a-str").AsSelf();
            
            // 注意一个builder对象不能同时Build()两次
            // Build()返回IContainer对象,用于通过特定算法获取注册的bean;
            var contailer = builder.Build();

            // 如果Program注入了两个bean这里只会取出最后注入的那个
            var program = contailer.Resolve<Program>();
            // 输出了数据里防静电,说明两个bean都注入成功,且完成的Program属性的装配;
            Console.WriteLine(program.Name);
            // 还可以通过这种方式获取注入的某种类型的所有的bean;
            var programs = contailer.Resolve<IList<Program>>();
            Console.WriteLine(programs.Count);
            Console.WriteLine("Hello World!");
            
            var listStrType = typeof(List<>).MakeGenericType(typeof(string));
            var listStrInstance = Activator.CreateInstance(listStrType);
            listStrType.GetMethod("Add").Invoke(listStrInstance, new object[]{"u"});

            /**
             * 这里给大家提供一下Spring里的@Resource和@Primary以及@Component的实现方式:
             * 1.@Component其实是最简单的,就是通过builder.RegisterType(type);来实现,
             * 先是通过AppDomain.CurrentDomain.GetAssemblies().Where(a => a.GetCustomAttributes()...)找出那些有[Component]特性的类,然后将他们注册到Autofac里;
             *
             * 2.@Resource就是在1的基础上通过builder.Register(c => new Program(){Name = c.Resolve<string>()})和反射先创建Program对象,
             * 然后来对每个要注入的类判断其所有的属性找出那些有[Resource]的还是通过反射来注入属性;
             *
             * 3.@Primary它是和@Component一样是注解在需要生产bean的类上面,这个实现其实就是在2的基础上c.Resolve(type)时的这个type是通过typeof(IList<>)的
             * MakeGenericType(有@Resource的属性的Type类型),然后就可以将所有的和属性同类型的(Spring里是有byType和byName的说法,这里假设就是byType)bean都找出来
             * 然后如果list里只有一个则直接装配,如果多个则找出有@Primary的那个bean(这几个bean有共同的接口),如果都没有则可以像Spring一样抛出异常;
             */
        }
    }

  

 

posted on 2019-01-05 19:24  Silentdoer  阅读(484)  评论(0编辑  收藏  举报