Skip to content

dcvsling/Extensions.DependencyInjection.AttributeModel

Repository files navigation

AttributeModel.Extensions.DependencyInjection

.NET

簡介

這是以 Microsoft.Extensions.DependencyInjection 為主要 DI 容器 並且透過 Attribute 來設定注入方式

使用方式

安裝

在安裝的專案目錄下輸入指令

dotnet add package AttributeModel.Extensions.DependencyInjection

使用

一般類別庫僅需要透過以 Lifetime 為名的屬性對類別裝飾即可

[Singleton]
public class SingletonService {}

[Scoped(ServiceType = typeof(IScoped))]
public class ScopedService : IScoped {}

[Transient(ServiceType = typeof(ITransient<>))]
public class TransientService<T> : ITransient<T> { }

並且於最末端的專案 例如: Web專案 於該專案中註冊 DI 容器的地方加上下面這段 此處以 AspNetCore Web 專案中的 Startup.ConfigureService 為例

public void ConfigureService(IServiceCollection services)
{
	// 加上這行即可
	services.AddAttributeModelRegister();
}

運作方式

流程

簡單說明一下其內部運作方式

  1. 運用 SourceGenerator 中的分析器分析 Attribute 並將其轉換成為相對應的容器註冊的程式碼
  2. 將產生的程式碼寫在一個由當下 AssemblyId 的 Namespace 下名為 ServiceRegistryAttribute 的類別中
  3. 將該類別繼承 Attribute 並且於 Assembly 級別上直接宣告該 Attribute
  4. 最後 AddAttributeModelRegister 就是在所有載入的 Assembly 中找出所有的 ServiceRegistryAttribute 並且將 IServiceCollection 帶入並完成註冊

優點

  • 一般 Attribute 類型的做法都必須透過於執行階段去掃描所有的類型,
    而透過 SourceGenerator 則是在設計階段就完成所需要的註冊程式碼,
    於執行階段僅搜尋到 Assembly Level 的 Attribute,
    啟動時的效能可以好很多
  • 由於 dotnet 內建的 DI 容器幾乎是沒有開放擴展的,
    因此如果想要實現比較特殊的模式 (ex: 裝飾器模式), 會變得異常的困難或是複雜, 透過 設計階段的 Attribute 來實現註冊等同於額外提供了一個重新設計的註冊方式的空間,
    因此可以大幅度的加強其可擴展性
    (但我還沒實現這件事情 orz)

缺點

  • 因為 Attribute 無法使用 非 const 的參數
    因此在必須透過方法的實現註冊的案例中
    那些方法該放在哪裡變得有點尷尬
    不過由於 dotnet 的 DI 註冊方式已經盡可能地避免這件事情發生 以及目前也已經實現一種做法來提供這部分的需求

提示

所有註冊容器所使用的各式自定義的方法
都離不開最初提供的那幾個註冊方式 例如:

services.Configure<MyOptions>(options => configuration.Bind(options));

實際上他背後程式碼請參考連結 source 透過原始碼發現他是用一個 class 裝載那段 lambda 並且註冊為 IConfigureOptions 以及 Singleton 因此透過下面做法也可以達到一樣的效果

[Singleton(ServiceType = typeof(IConfigureOptions<MyOptions>))]
public class MyOptionsConfigureOptions : IConfigureOptions<MyOptions> 
{
	private readonly IConfiguration _configuration;
	public MyOptionsConfigureOptions(IConfiguration configuration) 
	{
		_configuration = configuration;
	}
	public void Configure(MyOptions options)
	{
		_configuration.Bind(options);
	}
}

版本

0.2.0

註冊裝飾器

在這個版本中引用了套件 Scrutor
透過此套件的裝飾器功能
現在可以透過 Decorator 屬性來註冊裝飾器

public interface IA 
{
    void Invoke();
}

[Decorator(serviceType = typeof(IA))]
public class A : IA 
{
    private readonly IA _a;
    public A(IA a) 
    {  
        _a = a;
    } 
    public void Invoke() 
    { 
        _a.Invoke()
    }
}

由於 Scrutor 的裝飾器做法
必須在裝飾器註冊之前註冊被裝飾類別 這個困境在這裡將會被有效的解決 裝飾器將會在所有其他透過 Attribute 進行的註冊之後
才會開始註冊裝飾器 但如果需要保證註冊成功
亦需要於將 AddAttributeModelRegister 方法於最後註冊

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages