動手造輪子:實現一個簡單的依賴註入(三) 支持屬性註入 Intro 前面寫了幾篇依賴註入的文章,有興趣的小伙伴可以參考文末 Reference 部分中的鏈接,一直有小伙伴希望增加屬性註入的支持,昨天試著加了一下,思路很簡單,在獲取到服務實例之後檢查實例中有沒有需要註入的屬性,如果有並且不為 null ...
動手造輪子:實現一個簡單的依賴註入(三) --- 支持屬性註入
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