我正在尝试创建一些代码来检测c#中接口的所有具体实现。但是我不相信我面临的问题仅限于c#,这是一个普遍的oop问题。
我想在运行时进行检测,因此我可以在将来扩展接口的实现。
为实现这一目标,我可以使用哪些选项/方法?
例如
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;}
}
由于
尼古拉斯
答案 0 :(得分:4)
您可以执行以下操作:
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容器答案 1 :(得分:1)
您可以使用反射相对轻松地完成此操作,例如:
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>());
有多种选项可以指定要扫描的程序集,如果使用安装程序,则可以使系统具有可扩展性。
答案 2 :(得分:0)
我可以看到你如何使用反射来实现这一点 - 从一个程序集到它的类,然后询问每一个以查看它是否可以转换为IWhatever - 但当然这种方法而不是c#-specific肯定是.net特异性。
对你有用吗?
答案 3 :(得分:0)
您可以使用具体类型实现的Type.IsAssignableFrom 信息 看它是否实现了一个接口(可以分配给它)。
良好的实施可以是这样的:
var type = typeof(IMyInteraface);
var types = AppDomain.CurrentDomain.GetAssemblies().ToList()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
您可以在接受的答案中找到:Getting all types that implement an interface
这自然只能看到当前域的类型。