C#如何在运行时动态生成实现不同接口的对象?

时间:2009-11-03 10:04:30

标签: c# dynamic interface

我正在研究如何解决问题,我甚至不确定这可能在C#& .NET 3.5:

假设我的接口数量有限,每个接口都描述一组特定的,不相关的方法。现在我有一些现实世界的设备,每个设备可能只实现这些接口的一部分。

在使用这些设备建立通信时,他们会告诉我他们有哪些功能。我现在想创建一个实现接口的对象(每个接口类似于设备的一个功能),以便在我的应用程序架构中更高,我能够:

  • 针对上述接口编写代码
  • 测试该生成的对象是否实现某个接口以查看是否支持某些操作

我根本不确定使用哪种方法解决这个问题。欢迎任何评论或方法!

6 个答案:

答案 0 :(得分:5)

使用mocking frameworkMoqRhinoMocks

TypeMock Isolator

如果你想做一些较低级别的事情,像Castle DynamicProxy这样的事情对你来说可能是个好方向。

答案 1 :(得分:3)

尝试类似LinFu.DynamicObject的内容。

答案 2 :(得分:1)

也许你不需要这么“动态”。

您检查了Abstract Factory模式吗?基本上,您需要的是基于设备类型为每个接口创建具体实现。

您不需要单个类实现大量接口,只要在代码请求时就可以适当实现特定接口。

抽象工厂的每个具体实现都可以根据您的设备类型生成多个接口实现。

示例:

 public interface IDeviceFactory
 {
      ISomething GetSomeInterface();
      ISomethingElse GetSomeOtherInterface();
 }

然后为每个设备实现特定工厂:

public class SimpleDeviceFactory : IDeviceFactory
{
     public virtual ISomething GetSomeInterface()
     { return Something.Empty; }

     public virtual ISomethingElse GetSomeOtherInterface()
     { return new SomeSimpleConreteImplementation(); }
}

或者也许:

public class ComplexDeviceFactory : IDeviceFactory
{
     public virtual ISomething GetSomeInterface()
     { return new ComplexStuff(); }

     public virtual ISomethingElse GetSomeOtherInterface()
     { return new EvenMoreComplexStuff(); }
}

然后,最后,您为设备创建了正确的工厂:

public class DeviceFactory
{
     public static IDeviceFactory CreateForDevice(IDevice device)
     {
          DeviceType type = device.Type; // or something like this
          switch (type)
          {
              case DeviceType.Simple: 
                 return new SimpleDeviceFactory();

              case DeviceType.Complex: 
                 return new ComplexDeviceFactory();

              default:
                 throw new NotImplementedException();
          }
     }
}

请注意,我还将IDeviceFactory方法实现标记为virtual,以便您可以轻松地重用或覆盖特定设备的特定接口。

答案 3 :(得分:0)

有可能,并不容易。您需要创建一个基本上是源文件的字符串,然后创建并使用CSharpCodeProvider,然后您可以命令编译代码。如果有效,您可以通过反射手动访问创建的对象。

对于感兴趣的人,我做了一段时间,细节有点模糊。

答案 4 :(得分:0)

.NET 4可能会更容易,您可以使用已经提到的框架之一或者去System.Reflection路由。你会在互联网上找到大量的样本。

我过去都做过这两件事。滚动我自己的il.Emit东西和使用框架(在我的情况下是Spring.NET)。除了琐碎的东西,使用其中一个框架。

答案 5 :(得分:0)

您也可以尝试使用Re-mix项目。该项目的一个主要特性是create mixins,它允许您将实现和状态的接口添加到其他类。看看这个例子:

using Remotion.Mixins;
using Remotion.TypePipe;
//...

public interface ITargetInterface
{
    void DoSomething();
}
// . . .
public class TargetImplementation : ITargetInterface
{
    public void DoSomething()
    {
        Console.WriteLine("ITargetInterface.DoSomething()");
    }
}
// . . .
public interface IMixinInterfaceA
{
    void MethodA();
}
// . . .
public class MixinImplementationA : IMixinInterfaceA
{
    public void MethodA()
    {
        Console.WriteLine("IMixinInterfaceA.MethodA()");
    }
}
// . . .
public interface IMixinInterfaceB
{
    void MethodB(int parameter);
}

// . . .
public class MixinImplementationB : IMixinInterfaceB
{
    public void MethodB(int parameter)
    {
        Console.WriteLine("IMixinInterfaceB.MethodB({0})", parameter);
    }
}

然后您可以合并这些类型以创建mixin:

var config = MixinConfiguration.BuildFromActive()
            .ForClass<TargetImplementation>()
            .AddMixin<MixinImplementationA>()
            .AddMixin<MixinImplementationB>()
            .BuildConfiguration();
MixinConfiguration.SetActiveConfiguration(config);

不幸的是,你不能简单地在TargetImplementation上调用new并期待一个混音。相反,您必须要求Re-mix创建一个TargetImplementation实例,以便它可以为您的规范构建一个新类型并实例化它。当询问TargetImplementation的实例时,它将返回包含所有接口和类的mixin。

ITargetInterface target = ObjectFactory.Create<TargetImplementation>(ParamList.Empty);

target.DoSomething();

var targetAsMixinA = target as IMixinInterfaceA;
if (targetAsMixinA != null)
{
   targetAsMixinA.MethodA();
}

var targetAsMixinB = target as IMixinInterfaceB;
if (targetAsMixinB != null)
{
    targetAsMixinB.MethodB(30);
}