1

我正在尝试创建一些代码来检测 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;}
}

谢谢

尼古拉斯

4

4 回答 4

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 容器

于 2013-05-14T14:57:08.367 回答
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();

然而,有一些担忧:

  1. 如果您在构造函数中有任何依赖关系,解决这些问题可能会变得非常复杂
  2. 您如何确定要探测哪些程序集?上面的例子只探测已经加载的程序集
  3. 你如何处理构造函数异常?

我建议查看控制容器(例如 Castle Windsor)的依赖注入/反转以及自动注册,例如:

 container.Register(AllTypes.FromAssemblyContaining<IAnimal>().BasedOn<IAnimal>());

有多种选项可以指定要扫描的程序集,如果您使用安装程序,则可以使您的系统具有相当大的可扩展性。

于 2013-05-14T15:01:53.533 回答
0

我可以看到你如何使用反射来做到这一点——从一个程序集到它的类,然后询问每个程序以查看它是否可以转换为 IWhatever——但当然,这种方法虽然不是 c# 特定的,但肯定是 .net 特定的。

对你有用吗?

于 2013-05-14T14:55:34.700 回答
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

这自然是只查看当前域的一种类型。

于 2013-05-14T14:56:33.863 回答