【问题标题】:Nuget Library to get all types that implement an interface in all assemblies and referenced assembliesNuget 库,用于获取在所有程序集中和引用程序集中实现接口的所有类型
【发布时间】:2021-12-07 06:43:00
【问题描述】:

我正在努力寻找一个好的答案。

我需要扫描所有实现接口IDomainEvent的类。

问题是那些类型在项目中不一定被加载。比如我的主程序集是WebApi,有一个依赖Application,它依赖于Domain,它又依赖于DomainEvents

因此,我没有一种“简单”的方法来获取所有实现 IDomainEvent 并在 *DomainEvents.csproj 项目中的类型

是否有任何 nuget 库可以动态导航所有引用的项目/程序集及其子依赖项并能够检索实现接口的所有类型?

它在启动时发生一次,所以我不太关心性能。

PS:下面的方法按预期返回0,因为程序集没有加载

var allDomainEventTypes =
  AppDomain
    .CurrentDomain
    .GetAssemblies()
    .SelectMany(x => x.GetTypes())
    .Where(t => t.IsAssignableTo(typeof(IDomainEvent)) && !t.IsInterface)
    .ToList();

【问题讨论】:

    标签: c# reflection .net-assembly


    【解决方案1】:

    你可以尝试一些类似的东西

    var definitions = typeof(YourTypeInsideAssembly).Assembly.GetImplementationsOf(typeof(IYourInterfaceType));
                foreach (var definition in definitions)
                {
                    //Do you thing with definition.
                }
    

    这需要为接口的每个实现指定YourTypeInsideAssembly。例如,如果您有一个项目有 3 个实现接口的类,而另一个项目有 4 个。您需要为每个项目指定两个类。 我认为这样你也强制加载程序集。

    附言

    这对我以前也有用:

     var allAssemblies = Assembly
                    .GetEntryAssembly()
                    .GetReferencedAssemblies()
                    .Select(Assembly.Load)
                    .ToArray();
    

    【讨论】:

    • 他可能需要递归使用 GetReferencedAssemblies() 来获取所有其他程序集。
    • 是的,我需要一些递归来获取所有程序集,然后从这些程序集中获取类型。上面的建议找不到我需要的类型(它们分布在多个项目中,没有被主程序集直接引用)。这就是为什么我试图找到一个已经为给定接口类型作为输入的库
    【解决方案2】:

    我没有找到任何好的东西。 我有以下解决方法(感谢this great article

    public static class AssemblyExtensions
    {
        public static IEnumerable<Assembly> GetAllAssemblies(this Assembly rootAssembly)
        {
            var returnAssemblies = new List<Assembly>();
            var loadedAssemblies = new HashSet<string>();
            var assembliesToCheck = new Queue<Assembly>();
    
            assembliesToCheck.Enqueue(rootAssembly);
    
            while (assembliesToCheck.Any())
            {
                var assemblyToCheck = assembliesToCheck.Dequeue();
    
                foreach (var reference in assemblyToCheck.GetReferencedAssemblies())
                {
                    var fullName = reference.FullName;
                    if (!loadedAssemblies.Contains(fullName))
                    {
                        var assembly = Assembly.Load(reference);
                        assembliesToCheck.Enqueue(assembly);
                        loadedAssemblies.Add(fullName);
                        returnAssemblies.Add(assembly);
                    }
                }
            }
    
            return returnAssemblies;
        }
    }
    

    它运行良好,因为它能够“递归”加载引用的程序集,因此我可以检索实现给定接口的所有类型。

    但是,请注意,引用一个项目并不一定意味着如果没有使用该项目的类,则该程序集将被引用。

    var domainEventTypes = 
        typeof(Startup)
            .Assembly
            .GetAllAssemblies()
            .SelectMany(x => x.GetTypes())
            .Where(t => t.IsAssignableTo(typeof(IDomainEvent)))
            .ToList();
    

    【讨论】:

      猜你喜欢
      • 2011-01-15
      • 1970-01-01
      • 1970-01-01
      • 2015-09-16
      • 1970-01-01
      • 2019-09-06
      • 1970-01-01
      • 1970-01-01
      • 2020-08-24
      相关资源
      最近更新 更多