動手造輪子:實現一個簡單的依賴注入(三) — 支持屬性注入

動手造輪子:實現一個簡單的依賴注入(三) — 支持屬性注入

Intro

前面寫了幾篇依賴注入的文章,有興趣的小夥伴可以參考文末 Reference 部分中的鏈接,一直有小夥伴希望增加屬性注入的支持,昨天試着加了一下,思路很簡單,在獲取到服務實例之後檢查實例中有沒有需要注入的屬性,如果有並且不為 null 就從服務容器中獲取一個對應屬性類型的實例

代碼修改

FromServiceAttribute

完整的代碼修改可以參考這個 commit https://github.com/WeihanLi/WeihanLi.Common/commit/91dc0b515d12e7c036771fba9419824cd0219544

首先我們需要增加一個 FromServiceAttribute 用來標識哪些屬性需要注入,代碼如下:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
public sealed class FromServiceAttribute : Attribute
{
}

這裏 AttributeTargets 除了屬性之外增加了字段和參數,是想可能以後會用到,參數典型的應用場景就是類似於 asp.net core 里的 [FromServices] 用來實現方法注入參數

EnrichObject

增加了一個 EnrichObject 方法,用來在獲取到服務實例之後,對服務實例做一些補充的配置,如我們要加的屬性注入,如果我們要加字段注入等也可以在這個方法內完成,來看實現:

private object EnrichObject(object obj)
{
    if (null != obj)
    {
        // PropertyInjection
        var type = obj.GetType();
        foreach (var property in CacheUtil.TypePropertyCache.GetOrAdd(type, t => t.GetProperties())
            .Where(x => x.IsDefined(typeof(FromServiceAttribute))))
        {
            if (property.GetValueGetter()?.Invoke(obj) == null)
            {
                property.GetValueSetter()?.Invoke(
                    obj,
                    GetService(property.PropertyType)
                    );
            }
        }
    }

    return obj;
}

上面的邏輯就是獲取這個 object 定義的所有需要注入的屬性,如果屬性的值不為 null 則,從服務容器中獲取對應的服務實例,之所以要檢查是不是null

上面的 CacheUtil.TypePropertyCache 是一個 Type 為 key,PropertyInfo 數組為 Value 的併發字典,用來緩存類型的屬性

GetValueGetter/GetValueSetter 是 PropertyInfo 的擴展方法,利用表達式樹和緩存提高屬性 Get/Set 的效率

GetSertviceInstance

修改原來的 GetServiceInstance 方法為 GetServiceInstanceInternal,增加一個一樣的方法,實現邏輯是在 GetServiceInstanceInternal 的基礎上調用上面的 Enrich 方法來實現屬性注入

More

雖然增加了屬性注入的支持,但是還是不太推薦使用,從上面屬性注入的代碼中可以看得到,如果用不好很容易出現循環依賴的問題,而且用構造器注入的話依賴關係很清晰,分析方法的構造方法即可,如果要使用屬性注入請謹慎使用

Reference

  • https://github.com/WeihanLi/WeihanLi.Common/commit/91dc0b515d12e7c036771fba9419824cd0219544
  • https://github.com/WeihanLi/WeihanLi.Common/tree/dev/src/WeihanLi.Common/DependencyInjection
  • https://www.cnblogs.com/weihanli/p/implement-dependency-injection.html
  • https://www.cnblogs.com/weihanli/p/implement-dependency-injection-01.html
  • https://www.cnblogs.com/weihanli/p/implement-dependency-injection-02.html

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

※回頭車貨運收費標準