获取在.NET Core中实现接口的所有类型

时间:2016-07-18 18:10:16

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

使用反射,我如何获得在 .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错误。

6 个答案:

答案 0 :(得分:14)

你可以这样做:

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()

答案 1 :(得分:6)

在.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包。

答案 2 :(得分:5)

获取所有实现类型&#39; T&#39;

的类的完整代码
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);
            }
        }
    }            
}

答案 3 :(得分:2)

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

答案 4 :(得分:0)

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

 private List<KvPair> RebuildList(object extendData)  //extendedData  is xml
  {
    List<KvPair> source = new List<KvPair>
    {
       new KvPair {Key = null, Value = "Null"},
       new KvPair {Key = 0, Value = "No"},
       new KvPair {Key = 1, Value = "Yes"}      
    };
    List<int> target = new List<int>();
    var data = XDocument.Parse(extendData.ToString()).Descendants("elem");
    int tempVal;

    foreach (var elem in data)
    {
      var key = Int32.TryParse(elem.Attribute("Value").Value,
             out tempVal) ? tempVal : null;
      target.Add(key)
    }
   source.RemoveAll(x => !target.Contains(x));

   return new List<KvPair>(source);
}

答案 5 :(得分:0)

一个可能的解决方案是告诉接口谁是用[ServiceKnownTypeAttribute]实现它的对象,当你需要知道实现get by reflexion的类型时。例如:

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;
    }