.Net Core DI,如何在程序集中注册所有现有的可分配类型

 

介绍

.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.");
      }
   }
}

 配置Dot Net core DI时,将使用第一种方法RegisterAllAssignableTypes。因此,您将看到如下一行:

services.RegisterAllAssignableType<ITaxCalculator><itaxcalculation>("MyApp.ExtendedLogics");

它将读取MyApp中的所有类。扩展项目,实现ITaxCalculator并在DI容器中将其注册为Transient 

因此,在使用者类中,您只需要向构造函数中添加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);

兴趣点

我已经了解了更多有关.Net Core DI的知识,这似乎将是.Net应用程序的新一代。

发布了69 篇原创文章 · 获赞 133 · 访问量 44万+

猜你喜欢

转载自blog.csdn.net/mzl87/article/details/104118425