我一直在尝试查找所有实现某个接口的类。我以前从未接触过任何类型的反思,所以我对此还很陌生。话虽如此,我已经根据一堆文章和堆栈溢出帖子实现了几种方法,但仍然无法使其工作。
问题是我似乎找不到在.NET6中跨多个程序集实现接口的类。
为了给您提供一些背景信息,我当前的测试实现很好地总结了问题。
注意:如果程序集之间的引用很重要,则 AssemblyA -> AssemblyB、AssemblyC -> AssemblyB
//Assembly A
public class SomeFunnyClass
{
public static void Main(string[] args)
{
Assembly.LoadFrom("AssemblyB.dll");
Assembly assemblyC = Assembly.LoadFrom("AssemblyC.dll");
SomeTests(assemblyC);
}
public void SomeTests(Assembly assembly)
{
var test = assembly.GetType("TestLoading").GetInterfaces(); // ILoading
var test2 = typeof(ILoading).IsAssignableFrom(assembly.GetType("TestLoading")); // false
}
}
这已经是我的问题了,在我的第一次测试中,我得到了正确的接口名称
ILoading
。
但在第二个测试用例中,我得到了 false
,我希望是 true
。
// Assembly B
public interface ILoading
{
void OnLoad();
}
// Assembly C
public class TestLoading : ILoading
{
public void OnLoad(){
// Do some cool stuff here
}
}
我已经尝试了几种不同的方法,但最终总是得到相同的结果。我还确保加载了所有必需的程序集。
有人知道为什么找不到
TestLoading
类吗?
您需要加载当前程序集,然后获取其位置和名称。然后,您(从给定位置)搜索目录中的所有
.dll
并使用以程序集名称开头的文件过滤搜索(如果您的所有类型都位于具有不同命名空间的同一程序集下,例如 (Project, Project.核心、项目..等)。
这是我从我的一个旧项目中获得的工作代码,它将帮助您理解逻辑。该类只会加载以当前程序集名称开头的程序集,并缓存类型,因此可以重用它,而无需再次重新加载程序集。
public static class TypeLoader
{
private static Type[] _loadedTypes;
private static IEnumerable<Type> GetLoadedTypes()
{
var assembly = Assembly.GetExecutingAssembly();
var location = assembly.Location;
var folder = location[..location.LastIndexOf('\\')];
var assemblyName = assembly.GetName().Name;
var index = assemblyName.IndexOf('.');
var offset = index == -1 ? assemblyName.Length : index;
var searchPattern = string.Format("{0}*.dll", assemblyName.Substring(0, offset));
foreach (var file in Directory.GetFiles(folder, searchPattern))
{
foreach (var type in Assembly.LoadFrom(file).GetTypes())
{
yield return type;
}
}
}
public static IEnumerable<T> GetInstances<T>() where T : class
{
if(_loadedTypes == null)
_loadedTypes = GetLoadedTypes().ToArray();
foreach (var type in _loadedTypes.Where(x => (x.IsSubclassOf(typeof(T)) || typeof(T).IsAssignableFrom(x)) && x.IsClass && !x.IsAbstract))
{
yield return Activator.CreateInstance(type) as T;
}
}
}
请注意,如果您使用 .NET5+,则应避免此类工作,而应使用 DI。