zoukankan      html  css  js  c++  java
  • ASP.NET Core 2.2 基础知识(一) 依赖注入

    依赖:

    类A用到了类B,我们就说类A依赖类B.如果一个类没有任何地方使用到,那这个类基本上可以删掉了.

        public class Test
        {
            private MyDependency md = new MyDependency();
    
            public void Print()
            {
                md.Print();
            }
        }
        public class MyDependency
        {
            public void Print()
            {
                Console.WriteLine("this is mydependency");
            }
        }

    上面的示例中,Test 类就依赖 MyDependency 类.

    依赖倒置:

    依赖倒置原则是五大原则之一:

    1.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象.

    2.抽象不能依赖于具象,具象依赖于抽象.

    什么是上层?使用者就是上层,上例中,Test 类就是上层.

    什么是下层?被使用者就是下层.上例中,Test 类使用了 MyDependency 类, MyDependency 类就是下层.

    上层不应该依赖下层,Test 类不应该依赖 MyDependency 类,因为如果 MyDependency 类变化了,就是把这种变化所造成的影响传递到上层 Test 类.

    因此,上例按照依赖倒置原则修改如下:

        public class Test
        {
            private IDepenency md = new MyDependency();
    
            public void Print()
            {
                md.Print();
            }
        }
        public interface IDepenency
        {
            void Print();
        }
    
    
    
        public class MyDependency : IDepenency
        {
            public void Print()
            {
                Console.WriteLine("this is mydependency");
            }
        }

    控制反转(IoC):Inversion of Control

    控制反转是一种思想,所谓"控制反转",就是反转获得依赖对象的过程.或许,叫"反转控制"更容易理解.

    上例虽然遵循了"依赖倒置原则",但是违背"开放封闭原则",因为如果有一天想修改 md 为 YourDependency 类的实例,则需要修改 Test 类.因此,我们需要反转这种创建对象的过程. 

        internal class Program
        {
            private static void Main(string[] args)
            {
                Test test = new Test(new MyDependency());
                test.Print();           
                Console.ReadKey();
            }
        }
    
        public class Test
        {
            private IDepenency md;
    
            public Test(IDepenency depenency)
            {
                md = depenency;
            }
    
            public void Print()
            {
                md.Print();
            }
        }

    上例中,将 md 的创建过程"反转"给了调用者.

    依赖注入(DI):Dependency Inject 

    依赖注入设计模式是一种在类及其依赖对象之间实现控制反转(IOC)思想的技术.

    所谓依赖注入,就是由IoC容器在运行期间,动态地将某种依赖关系注入到对象之中。

    我们先创建一个简易的IoC容器(当然,实际的 IoC 容器复杂得多.):

        public class IoCContainer
        {
            private Dictionary<Type, Object> dic;
    
            public IoCContainer()
            {
                Init();
            }
    
            private void Init()
            {
                dic = new Dictionary<Type, object>
                {
                    {typeof(IDepenency),new MyDependency() }
                };
            }
    
            public T GetInstance<T>()
            {
                return (T)dic[typeof(T)];
            }
        }

    那么,上例的调用,则可以修改成:

        internal class Program
        {
            private static void Main(string[] args)
            {
                IoCContainer container = new IoCContainer();//创建一个容器
                IDepenency dependency = container.GetInstance<IDepenency>();//获取注册的实例
                Test test = new Test(dependency);
                test.Print();
                Console.ReadKey();
            }
        }

    依赖注入分为3中:构造函数注入,属性注入,方法注入,上例属于构造函数注入.

    ASP.NET Core 中的依赖注入

    ASP.NET Core 内置的IoC容器,只支持构造函数注入,注入的方式如下:

    在 Startup 类的 ConfigureServices 方法中注册.

            public void ConfigureServices(IServiceCollection services)
            {            
           services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    //DI services.AddTransient<IDependency, MyDependency>(); }

    使用:

        [Route("api/[controller]")]
        [ApiController]
        public class ValuesController : ControllerBase
        {
            private readonly IDepenency _dependency;
            public ValuesController(IDepenency dependency)
            {
                _dependency = dependency;
            }
            
            ...other codes
      }

    生存期

    这是依赖注入设计原则里一个非常重要的概念,ASP.NET Core 一共有3种生存期:

    1.暂时(Transient) : services.AddTransient<IDependency, MyDependency>(); 顾名思义,这种生存期的对象是暂时的,每次请求都会创建一个新的实例.

    2.作用域(Scoped) : services.AddScoped<IDepenency, MyDependency>(); 每次请求使用的是同一个实例.

    3.单例(Singleton) : services.AddSingleton<IDepenency, MyDependency>(); 第一次请求时就创建,以后每次请求都是使用的相同的实例.

    这种生存期的对象还有一种注册方式:  services.AddSingleton<IDepenency>(new MyDependency());

    这种方式与其他所有方式的区别在于:如果 MyDependency 实现了  IDisposable ,那么其他方式注册的实例,容器会自动释放,也就是说,容器创建的实例会自动释放,但这种方式不会,因为这种方式注册的实例不是容器创建的.

    官方文档建议:

    依赖注入是静态/全局对象访问模式的替代方法.如果将其与静态对象访问混合使用,则可能无法实现依赖关系注入的优点。

    ps 还没搞明白的问题:

    OperationService 依赖  IOperationTransient,IOperationScoped,IOperationSingleton,IOperationSingletonInstance,但是它只能注册 暂时和作用域 生存期,不能注册单例生存期

                    services.AddTransient<IOperationTransient, Operation>();
                    services.AddScoped<IOperationScoped, Operation>();
                    services.AddSingleton<IOperationSingleton, Operation>();
                    //通过代码将实例添加到容器中.              
                    services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
                    //OperationService 只能注册临时和作用域生存期
                    services.AddTransient<OperationService, OperationService>();
  • 相关阅读:
    求n的元素的最大最小值
    输出一个集合的所有子集,从长到短
    树的各种操作java
    几个笔试题目总结
    小知识不断补充
    java、C语言实现数组模拟栈
    LearnHowToThink
    Android中的this、Activity、Context等
    Android已上线应用开源分享中(第二季)
    Android已上线应用开源分享中(第一季)
  • 原文地址:https://www.cnblogs.com/refuge/p/10206542.html
Copyright © 2011-2022 走看看