最近,我使用了ASP锅炉示例。它有一些类来实现依赖项注入,例如ITransientDependency
。
当一个类实现ITransientDependency
接口时,它可以被注入构造函数,而无需在启动文件中进行任何配置。
我也想这么做,但不知道怎么做。请告诉我该怎么办,有图书馆可以支持还是有文档。
您可以通过反射来实现这一点,但这并非微不足道。
以下假设您已经设置了依赖项注入容器。
步骤1
首先,您需要从所有当前程序集中获取所有类型,但只能获取那些不是抽象或接口的类型(即可以创建的类型(:
var types = from t in AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes())
where t.IsAssignableFrom(typeof(ITransientDependency))
&& !t.IsAbstract && !t.IsInterface
select t;
这将返回Type
对象的列表,这些对象表示从所有当前加载的程序集中实现ITransientDependency
的类。
步骤2
接下来,您需要将它们添加到依赖注入容器中。假设您使用的是Microsoft的IServiceCollection
,那么您可以这样做(例如,在Startup类中的ConfigureServices
方法中(:
foreach (var t in types)
{
services.AddTransient(t);
}
注意:这并不是真正的DI最佳实践。通常,您应该注入接口,而不是实现,并像这样添加每个接口:
services.AddTransient<ISomeDependency, SomeImpl>();
services.AddTransient<IAnotherDependency, AnotherImpl>();
// and so on
这有助于测试驱动的开发,因为您可以创建接口的模拟实现,但不能创建实现。
步骤3
最后,您现在可以通过构造函数将这些注入到类中:
public class SomeClass
{
public SomeClass(SomeDependency dep)
{
// do something
}
}
这样做需要小心,因为您可能会在运行时引入问题-例如,所有ITransientDependency
实现的依赖项也需要添加到DI容器中,并且它们不能有任何其他依赖项(例如值类型(。
警告
第一步中使用的GetTypes()
方法可能引发异常,因此需要处理该异常。我过去曾通过将其推广到一种扩展方法中来做到这一点:
internal static IEnumerable<Type> GetLoadableTypes(this Assembly assembly)
{
try
{
return assembly.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
return e.Types.Where(t => t != null);
}
}