在运行时检测接口的所有具体实现
本文关键字:实现 运行时 检测 接口 | 更新日期: 2023-09-27 18:13:36
我正在尝试创建一些代码来检测c#中接口的所有具体实现。然而,我不相信我所面临的问题是局限于c#,是一个普遍的面向对象问题。
我想在运行时进行检测,这样我就有能力在将来扩展接口的实现。
为了实现这一目标,我有哪些选择/方法?
例如public interface IAnimal{
void MakeNoise();
}
public class Dog : IAnimal{
public void MakeNoise()
{
Console.WriteLine("WOOF");
}
}
public class Cat : IAnimal{
public void MakeNoise()
{
Console.WriteLine("Meow");
}
}
public class AnimalInstanceController{
/*Im trying to populate this with all classes that implement IAnimal
*/
public IEnumerable<IAnimal> {get;set;}
}
感谢尼古拉斯
您可以这样做:
var implementations = new List<Type>();
foreach (Assembly assembly in <collection of assemblies you want to scan>)
{
foreach (Type type in assembly.GetTypes())
{
if (type.GetInterfaces().Contains(typeof(IAnimal)))
{
implementations.Add(type);
}
}
}
或者使用像Autofac这样的DI容器
使用反射可以相对容易地做到这一点,例如:
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var allTypes = assemblies.SelectMany(x => x.GetTypes());
var implTypes = allTypes.Where(t => !t.IsInterface && !t.IsAbstract)
.Where(t => typeof (IAnimal).IsAssignableFrom(t));
var animals = implTypes.Select(t => (IAnimal) Activator.CreateInstance(t))
.ToArray();
然而,有一些问题:
- 如果你在构造函数中有任何依赖项,那么解析这些 会变得相当复杂。
- 如何确定要探测的程序集?上面的例子只探测已经加载的程序集 如何处理构造函数异常?
我建议看看依赖注入/控制反转容器,如Castle Windsor以及自动注册,例如:
container.Register(AllTypes.FromAssemblyContaining<IAnimal>().BasedOn<IAnimal>());
有不同的选项来指定要扫描的程序集,如果你使用安装程序,你可以使你的系统非常可扩展。
我可以看到您如何使用反射来做到这一点-从程序集到它的类,然后询问每个类,看看它是否可以被强制转换为I - whatever -当然,这种方法虽然不是c#特定的,但肯定是。net特定的。
对你有用吗?
您可以使用Type。来自具体类型实现的信息看看它是否实现了一个接口(可以这样分配给它)。
好的一致性实现可以像这样:
var type = typeof(IMyInteraface);
var types = AppDomain.CurrentDomain.GetAssemblies().ToList()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
,你可以在以下的可接受答案中找到:获取实现接口的所有类型
这自然是只查看当前域的一个类型。