【问题标题】:Getting all types that implement an interface in .NET Core获取在 .NET Core 中实现接口的所有类型
【发布时间】:2016-11-21 10:51:18
【问题描述】:

使用反射,我如何获得所有在 .NET Core 中实现特定接口的类型?我注意到 .NET 4.6 中可用的方法不再可用。

例如,此代码不起作用。

var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(s => s.GetTypes())
    .Where(p => type.IsAssignableFrom(p));

它会抛出 The name 'AppDomain' does not exist in the current context 错误。

【问题讨论】:

  • 我确信代码可以正常工作,只是你没有AppDomain。
  • @BlueEyedBehemoth 所以如何包含 AppDomain? :D
  • 你需要它做什么?这通常不是你惹的祸。
  • @BlueEyedBehemoth 这是一个非常标准的插件支持模式。
  • @HansPassant 这不是真的。人们可能会在不会移植到 CoreRT 的环境中使用 Core。假设每个人都会将他们的代码移植到 CoreRT 是不屑一顾的。

标签: c# .net reflection lambda .net-core


【解决方案1】:

获取所有实现类型'T'的类的完整代码

public static IEnumerable<T> GetAll<T>()
{
    var assembly = Assembly.GetEntryAssembly();
    var assemblies = assembly.GetReferencedAssemblies();

    foreach (var assemblyName in assemblies)
    {
        assembly = Assembly.Load(assemblyName);

        foreach (var ti in assembly.DefinedTypes)
        {
            if (ti.ImplementedInterfaces.Contains(typeof(T)))
            {
                yield return (T)assembly.CreateInstance(ti.FullName);
            }
        }
    }            
}

【讨论】:

    【解决方案2】:

    在 .NET Core 2.0 中,您可以在程序集中找到所有在编译时已知的匹配类型(这不适用于动态加载的程序集),如下所示:

    private static IEnumerable<Type> GetAllTypesOf<T>()
    {
        var platform = Environment.OSVersion.Platform.ToString();
        var runtimeAssemblyNames = DependencyContext.Default.GetRuntimeAssemblyNames(platform);
    
        return runtimeAssemblyNames
            .Select(Assembly.Load)
            .SelectMany(a => a.ExportedTypes)
            .Where(t => typeof(T).IsAssignableFrom(t));
    }
    

    这依赖于Microsoft.Extensions.DependencyModel 包。

    【讨论】:

      【解决方案3】:

      一个可能的解决方案是使用[ServiceKnownTypeAttribute] 告诉接口谁是实现它的对象,以及何时需要通过反射知道实现 get 的类型。示例:

      public class TypeWithImplementOne : IMyInterface
      {
        public string Hi()
        {
          return "hi";
        }
      
      }
      public class TypeWithImplementTwo : IMyInterface
      {
         public string Hi()
        {
          return "hi";
        }
      }
      public interface IMyInterface{
      {
        [ServiceKnownType(typeof(TypeWithImplementOne))]
        [ServiceKnownType(typeof(TypeWithImplementTwo))]
      
        string Hi();
      }
      

      您可以恢复使用以下实现的类型:

      private IEnumerable<string> GetKnownTypes()
          {
              List<string> result = new List<string>();
      
              Type interfaceType = typeof(IMyInterface);
              IEnumerable<CustomAttributeData> attributes = interfaceType.CustomAttributes
                  .Where(t => t.AttributeType == typeof(ServiceKnownTypeAttribute));
      
              foreach (CustomAttributeData attribute in attributes)
              {
                  IEnumerable<CustomAttributeTypedArgument> knownTypes = attribute.ConstructorArguments;
                  foreach (CustomAttributeTypedArgument knownType in knownTypes)
                  {
                      result.Add(knownType.Value.ToString());
                  }
              }
      
              result.Sort();
              return result;
          }
      

      【讨论】:

        【解决方案4】:

        你可以这样做:

        System.Reflection.Assembly ass = System.Reflection.Assembly.GetEntryAssembly();
        
        foreach (System.Reflection.TypeInfo ti in ass.DefinedTypes)
        {
            if (ti.ImplementedInterfaces.Contains(typeof(yourInterface)))
            {
                ass.CreateInstance(ti.FullName) as yourInterface;
            }  
        }
        

        如果您想要所有程序集中的类型,只需使用以下内容获取所有引用并再次执行上述操作即可:)

        ass.GetReferencedAssemblies()
        

        【讨论】:

        • 只获取单个程序集中的类型,而不是所有加载的程序集。
        • 简写使用 LINQ var types = Assembly.GetEntryAssembly().DefinedTypes.Where(ti => ti.ImplementedInterfaces.Contains(typeof(ILogger))).Select(m => m.FullName);
        【解决方案5】:

        如果你想要所有程序集中的类型,只需简单地使用以下获取所有引用并再次执行上述操作即可:)

        ass.GetReferencedAssemblies()
        

        【讨论】:

          【解决方案6】:

          据我所知,没有办法在 .Net Core 1.0 中获取所有已加载的程序集。 It seems a way to do this is planned for 1.1.

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-07-08
            • 2010-09-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-11-22
            • 1970-01-01
            相关资源
            最近更新 更多