事情的原因
在进行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
实现这个方法。
测试后发现完全没问题,可以注入。