事情的原因
在進行asp.net core開發的時候,使用原生的ioc,每一個service都要注入,產生了一堆無用的配置文件,所以想有沒有一種方法,通過接口或者特性直接注入
嘗試
首先想到的是接口,所以我就用一個接口
/// <summary>
/// 創建一個接口,用於被類實現
/// </summary>
interface IService
{
}
然后在要注入的地方,實現這個類
/// <summary>
/// service層
/// </summary>
public class Service:IService
{
public string GetName()
{
return "This is Class";
}
}
使用擴展方法,里面寫一個反射,獲取這個接口的所有類
/// <summary>
/// 擴展方法
/// </summary>
/// <param name="services">要擴展的類</param>
/// <returns></returns>
public static IServiceCollection AddDataService(this IServiceCollection services)
{
//使用加載器技術,遍歷所有的類,篩選實現IService接口的類,並過判斷是否是類,並按照注解方式自動注入類
AppDomain.CurrentDomain.GetAssemblies()
//找到自己的類,WeButler是自己寫的命名空間
.FirstOrDefault(t => t.FullName.Contains("WeButler"))
//獲取所有對象
.GetTypes()
//查找是否包含IService接口的類
.Where(a=>a.GetInterfaces().Contains(IService))
//判斷是否是類
.Where(a=>a.IsClass))
//轉換成list
.ToList()
//循環,並添加到di中
.ForEach(t =>
{
services.AddScopet(t);
});
return services;
}
然后在Startup.cs
類中,實現這個重寫
public void ConfigureServices(IServiceCollection services)
{
services.AddDataService();
}
之后測試,沒問題。
進階
但是,我們要注入的類不只這一種,因為某些類需要單例注入並且,上面那種方法還要在實現一個接口,就在想能不能使用特性的方法,所以,對上面的方法進行了改造,首先要聲明一個特性
/// <summary>
/// 自動注入
/// 允許被繼承
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class DIAttribute : Attribute
{
public DIAttribute(Type dIType)
{
this.DIType = dIType;
}
public DIAttribute()
{
DIType = Type.OTHER;
}
public Type DIType { get; }
}
/// <summary>
/// 注入類型選擇
/// </summary>
public enum Type
{
/// <summary>
/// 單例模式
/// </summary>
SINGLETON,
/// <summary>
/// 其他模式
/// </summary>
OTHER
}
然后我們對剛剛的要注入的類進行改造
/// <summary>
/// service層
/// </summary>
[DI]
public class Service
{
public string GetName()
{
return "This is Class";
}
}
只需要加上DI特性就好了,其他的我們還是用剛剛的擴展方法來做
public static IServiceCollection AddDataService(this IServiceCollection services)
{
#region 處理依賴注入
//使用加載器技術,遍歷所有的類,篩選標記注解DI的類,並過濾掉抽象類,並按照注解方式自動注入類
AppDomain.CurrentDomain.GetAssemblies()
//找到自己的類
.FirstOrDefault(t => t.FullName.Contains("WeButler"))
//獲取所有對象
.GetTypes()
//查找是否包含DI特性並且查看是否是抽象類
.Where(a => a.GetCustomAttributes(true).Select(t => t.GetType()).Contains(typeof(DIAttribute)) && !a.IsAbstract)
//轉換成list
.ToList()
//循環
.ForEach(t =>
{
var Di = (DIAttribute)t.GetCustomAttributes(true).FirstOrDefault(d => d.GetType() == typeof(DIAttribute));
switch (Di.DIType)
{
case Attributes.Type.SINGLETON:
services.AddSingleton(t);
break;
case Attributes.Type.OTHER:
services.AddScoped(t);
break;
default:
services.AddScoped(t);
break;
}
});
#endregion
return services;
}
還是使用Startup.cs
實現這個方法。
測試后發現完全沒問題,可以注入。