提问人:Zer0 提问时间:10/1/2023 更新时间:10/1/2023 访问量:41
获取跨多个 .NET 程序集实现接口的类 [已关闭]
Get class that implements an interface across multiple .NET assemblies [closed]
问:
我一直在尝试找到实现某个接口的所有类。我以前从未进行过任何形式的反思,所以我对此有点陌生。话虽如此,我已经根据一堆文章和堆栈溢出帖子实施了几种方法,但仍然无法让它工作。
问题是我似乎找不到在 中实现跨多个程序集的接口的类。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
答:
0赞
iSR5
10/1/2023
#1
您需要加载当前程序集,然后获取其位置和名称。然后,在目录中搜索(从给定位置)的所有文件,并使用以程序集名称开头的文件筛选搜索(如果所有类型都位于具有不同命名空间的同一程序集下,例如 (Project、Project.Core、Project.Something ..等)。.dll
这是我从我的一个旧项目中获得的工作代码,它将帮助您理解逻辑。该类将仅加载以当前程序集名称开头的程序集,并缓存类型,因此可以重用它,而无需再次重新加载程序集。
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。
评论
typeof(ILoading)
ILoading