.Net Core DI,如何注册程序集中所有可赋值的类型





5.00/5 (2投票s)
在本文中,我们将解释如何在程序集中注册(添加)所有特定接口可赋值的类型,并在一个类中使用它们。
引言
.Net Core 带有它自己的依赖注入容器,并且 .Net Core 3.0 表明 .Net Core DI 可以是可靠和高效的。它仍然存在一些缺点。有很多扩展可以修复这些缺点,从而提供绝佳的机会。基本上,.Net core 使得编写和扩展它变得容易。
在本文中,我将向您展示如何添加一个新的扩展来注册所有可赋值于特定接口(类:接口)的类型。
如果您有用于某个任务的不同逻辑,并希望将它们存储在不同的类中并通过配置加载它们,这将很有帮助。
背景
假设您有特定的逻辑来计算员工的税款,并且您有几种类型的员工,每种员工类型都有自己的逻辑。因此,您将拥有一个接口,并且每种员工类型都应实现该接口。用户应该具有添加新员工类型的特性,这意味着用户还需要为新的员工类型添加新的逻辑。因此,基于开闭原则,我们不希望打开主代码进行更改,但我们需要为用户提供添加新逻辑的方式。因此,我们添加一个接口层和一个项目来添加新类。当用户添加新逻辑时,他应该重新启动应用程序,DI 将加载该项目中实现该接口的所有类。在这里,我们漂亮的扩展将发挥作用。
使用代码
正如您所看到的,该扩展非常简单易用,但它正在发挥魔力;)
public static class RegisterAllAssignableTypes
{
public static void RegisterAllAssignableType<T>(this IServiceCollection services, string assemblyName)
{
var assembly = AppDomain.CurrentDomain.Load(assemblyName);
var types = assembly.GetTypes().Where(p => typeof(T).IsAssignableFrom(p)).ToArray();
var addTransientMethod = typeof(ServiceCollectionServiceExtensions).GetMethods().FirstOrDefault(m =>
m.Name == "AddTransient" &&
m.IsGenericMethod == true &&
m.GetGenericArguments().Count() == 2);
foreach (var type in types)
{
if (type.IsInterface)
continue;
var method = addTransientMethod.MakeGenericMethod(new[] { typeof(T), type });
method.Invoke(services, new[] { services });
}
}
public static Interface ResolveByName<Interface>(this IServiceProvider serviceProvider, string typeName)
{
var allRegisteredTypes = serviceProvider.GetRequiredService<IEnumerable<Interface>>();
var resolvedService = allRegisteredTypes.FirstOrDefault(p => p.GetType().FullName.Contains(typeName));
if (resolvedService != null)
{
return resolvedService;
}
else
{
throw new TypeNotFound($"{typeName} type not found.");
}
}
}
第一种方法 RegisterAllAssignableTypes 将在您配置 Dot Net core DI 时使用。因此,您将有一行代码如下所示
services.RegisterAllAssignableType<ITaxCalculator><itaxcalculation>("MyApp.ExtendedLogics");
它将读取 MyApp.Extended 项目中实现 ITaxCalculator 的所有类,并将它们作为 Transient 注册到 DI 容器中。
因此,在消费者类中,您只需要将 IServiceProvider 添加到构造函数中即可。
public class EmployeeProcess
{
private readonly IServiceProvider _serviceProvider;
public(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
}
现在,当您从数据库加载员工并知道其类型时,您可以通过此扩展方法轻松加载其税收计算逻辑
var employeeType = employee.Type;
var employeeTaxLogic = _serviceProvider.ResolveByName<itaxcalculator>(employeeType);
var tax = employeeTaxLogic.CalculateTax(employee);
</itaxcalculator>
关注点
我更多地了解了 .Net Core DI,这似乎将在 .Net 应用程序中成为新一代。
历史
您可以通过 NuGet 访问此代码:MOME.DotNetDIExtensions
如果您使用它并报告其问题并推荐您的想法,以了解我们如何改进它以及您需要的 DI 扩展,我将非常高兴。这样,我可以将它们添加到此包中并开发和改进它。