Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 获取在.NET Core中实现接口的所有类型_C#_.net_Reflection_Lambda_.net Core - Fatal编程技术网

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

C# 获取在.NET Core中实现接口的所有类型,c#,.net,reflection,lambda,.net-core,C#,.net,Reflection,Lambda,.net Core,使用反射,如何获得在.NET Core中实现特定接口的所有类型?我注意到在.NET4.6中可用的方法不再可用 例如,此代码不起作用 var type = typeof(IMyInterface); var types = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(s => s.GetTypes()) .Where(p => type.IsAssignableFrom(p)); 它抛出当前上下文中不存在名称

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

例如,此代码不起作用

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

它抛出当前上下文中不存在名称“AppDomain”的错误。

据我所知,无法在.Net Core 1.0中获取所有加载的程序集

您可以这样做:

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

如果要在所有程序集中使用类型,只需使用以下命令获取所有引用,然后再次执行上述操作:)


如果要在所有程序集中使用类型,只需使用以下命令获取所有引用,然后再次执行上述操作:)


一个可能的解决方案是告诉接口谁是用
[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;
    }
private IEnumerable GetKnownTypes()
{
列表结果=新列表();
类型interfaceType=typeof(IMyInterface);
IEnumerable attributes=interfaceType.CustomAttributes
其中(t=>t.AttributeType==typeof(ServiceKnownTypeAttribute));
foreach(属性中的CustomAttributeData属性)
{
IEnumerable knownTypes=attribute.ConstructorArguments;
foreach(knownTypes中的CustomAttributeTypeArgument knownType)
{
Add(knownType.Value.ToString());
}
}
result.Sort();
返回结果;
}

获取实现类型“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);
            }
        }
    }            
}
公共静态IEnumerable GetAll()
{
var assembly=assembly.GetEntryAssembly();
var assemblies=assembly.getReferencedAssemblys();
foreach(程序集中的变量assemblyName)
{
assembly=assembly.Load(assemblyName);
foreach(组件中的变量ti。定义类型)
{
if(ti.ImplementedInterfaces.Contains(typeof(T)))
{
屈服返回(T)assembly.CreateInstance(ti.FullName);
}
}
}            
}

在.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));
}
private静态IEnumerable GetAllTypesOf()
{
var platform=Environment.OSVersion.platform.ToString();
var runtimeAssemblyNames=DependencyContext.Default.GetRuntimeAssemblyNames(平台);
返回运行时程序集名称
.Select(Assembly.Load)
.SelectMany(a=>a.ExportedTypes)
其中(t=>typeof(t).IsAssignableFrom(t));
}

这取决于软件包。

我确信代码工作正常,您只是没有
AppDomain
@BlueEyedBehemoth那么如何包含AppDomain呢?:你需要它做什么?通常你不会弄乱它。@BlueEyedBehemoth这是一个支持插件的标准模式。@HansPassant这不是真的。人们可能会在无法移植到CoreRT的环境中使用Core。假设每个人都将把他们的代码移植到CoreRT是不屑一顾的。这只获取单个程序集中的类型,而不是所有加载的程序集。使用LINQ var types=assembly.GetEntryAssembly().DefinedTypes进行速记。其中(ti=>ti.ImplementedInterfaces.Contains(typeof(ILogger)))。选择(m=>m.FullName);
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);
            }
        }
    }            
}
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));
}