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