web-dev-qa-db-ja.com

.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エラーをスローします。

13
Mr. Robot

あなたはこのようにすることができます:

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

.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 パッケージに依存しています。

7
Dave S

タイプ「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);
            }
        }
    }            
}
5
Edmilson Lani

私の知る限り、.Net Core 1.0で読み込まれたすべてのアセンブリを取得する方法はありません。 これを行う方法は1.1で計画されているようです。

2
svick

すべてのアセンブリで型が必要な場合は、次のコードを使用してすべての参照を取得し、上記を再度実行するだけです。)

ass.GetReferencedAssemblies()
0
littlewang

可能な解決策は、[ServiceKnownTypeAttribute]を使用してそれを実装するオブジェクトが誰であるかをインターフェースに通知し、必要なときに、実装によって返される型を知る必要がある場合です。例:

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;
    }
0
Miguel Remirez