C#接口。不指定派生类名

时间:2015-02-05 08:44:14

标签: c# interface

是否可以在派生类中运行方法而不必让基类知道它的名称。 IE:找出谁实现了ITest并运行该类中指定的方法。

我知道这个奇怪的问题。

class BaseClass
{

    public static void Main (string[] args)
    {
        ITest f; //Null here. Want this to auto magically look for classes implementing ITest.  
        f.Run (); //And then run this. #NoReflection #NoBlackMagic. 
    }
}

public interface ITest //This will live in the same file as BaseClass
{
    void Run ();
}


class Derrived : ITest //Lives in another file
{
    #region ITest implementation

    public void Run ()
    {
        Console.WriteLine ("Test was run");
    }

    #endregion
} 

这个想法是。让我们说BaseClass本身就是一个用户GUI,Derived类住在另一个文件的某个地方。

如果没有他/她担心硬编码的ITest f = new Derived() 类,那么给某人基本GUI类会很棒。

如果有更多的类实现ITest,那么如果它们都是Run();

就没问题

我已经看到了一些带有多态性的很酷的技巧,但你仍然需要定义类名。

也许我错过了接口点:(

干杯橡树。

1 个答案:

答案 0 :(得分:3)

反思就是这样做的方法。

您可以通过枚举程序集中的所有类来识别实现ITest的类:

var assembly = Assembly.GetExecutingAssembly();
var itestTypes = assembly.GetTypes().Where (t => t.IsClass &&
                                            typeof(ITest).IsAssignableFrom(t));
foreach (var t in itestTypes)
{
    Console.WriteLine (t.ToString());
    ITest test = (ITest)Activator.CreateInstance(t);
    test.Run();
}

依赖注入

实现此目的的另一种方法是使用依赖注入框架,例如Unity。它仍然在引擎盖下使用反射。

示例:在某些时候,您将注册要使用的类:

public static void RegisterClasses(IUnityContainer container)
{
    container.RegisterType<ITest, Derived>();
}

这表示“当某些内容需要ITest时,请创建Derived”的实例。

您的代码可能如下所示:

ITest f = container.Resolve<ITest>();
f.Run();

容器将查看其注册并选择Derived

其他选择是:

public class BaseClass
{
    private ITest _test;

    public BaseClass(ITest test) //injected, no knowledge of IUnityContainer required
    {
       _test = test;
    }
}

//elsewhere:
container.Resolve<BaseClass>();

或使用DependencyAttribute

public class BaseClass
{
    [Dependency]
    public ITest Test {get; set;}
}

//elsewhere:
container.Resolve<BaseClass>();

奖励是它不需要无参数构造函数,与第一段代码不同,它将以相同的方式“解析”所有参数,以便创建Derived