動手造輪子:實作一個簡單的依賴注入(三) --- 支持屬性注入
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
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/13510.html
標籤:.NET Core
