ASP.NET Core 2.2 基礎知識(一) 依賴注入

依賴:設計模式

類A用到了類B,咱們就說類A依賴類B.若是一個類沒有任何地方使用到,那這個類基本上能夠刪掉了.api

    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 類.函數

 

依賴倒置:ui

依賴倒置原則是五大原則之一:this

1.上層模塊不該該依賴於下層模塊,它們共同依賴於一個抽象.spa

2.抽象不能依賴於具象,具象依賴於抽象.設計

什麼是上層?使用者就是上層,上例中,Test 類就是上層.code

什麼是下層?被使用者就是下層.上例中,Test 類使用了 MyDependency 類, MyDependency 類就是下層.對象

上層不該該依賴下層,Test 類不該該依賴 MyDependency 類,由於若是 MyDependency 類變化了,就是把這種變化所形成的影響傳遞到上層 Test 類.blog

所以,上例按照依賴倒置原則修改以下:

    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>();
相關文章
相關標籤/搜索