在.NET 4.0中动态实现接口(C#)

时间:2010-06-04 13:55:19

标签: c# .net dynamic .net-4.0 c#-4.0

使用.NET 4.0中的新动态功能,似乎应该可以动态实现一个接口,例如:给出:

public interface IFoo 
{
    string Bar(int baz);
}

public class Foo : IFoo
{
    public string Bar(int baz) { return baz.ToString(); }
}

public class Proxy : IDynamicMetaObjectProvider
{
    private readonly object target;

    public Proxy(object target) { this.target = target; }

    // something clever goes here
}

然后我希望有一些方法可以写出来:

dynamic proxy = new Proxy(new Foo());
IFoo fooProxy = (IFoo)proxy; // because the target object implements it
string bar = fooProxy.Bar(123); // delegates through to the target implementation

但是,到目前为止,我还不确定用{。}替换// something clever goes here的内容。

所以,我的问题是:

  1. 这实际上可以用动态运行时吗?似乎动态实现方法和属性之类的东西相当容易,但我没有找到任何关于动态实现接口和转换的文档。

  2. 假设这是可能的,它有多难? (你可以假设我是一个体面的程序员,拥有丰富的反思经验,但对动态框架不熟悉。)

  3. 是否有任何资源可以帮助我指明实现这样的事情的正确方向?或者甚至已经完成这种事情的样本我可以作为一个起点?

5 个答案:

答案 0 :(得分:41)

开源框架Impromptu-Interface旨在实现此目的。它生成缓存的轻量级 使用静态接口的代理,并使用dlr将调用转发给原始对象。

using ImpromptuInterface;

public interface ISimpeleClassProps
{
    string Prop1 { get;  }

    long Prop2 { get; }

    Guid Prop3 { get; }
}

-

dynamic tOriginal= new ExpandoObject();
tOriginal.Prop1 = "Test";
tOriginal.Prop2 = 42L;
tOriginal.Prop3 = Guid.NewGuid();

ISimpeleClassProps tActsLike = Impromptu.ActLike(tOriginal);

答案 1 :(得分:13)

据我所知,如果没有人工干预,编写或生成将接口成员转发到包装实例的代码是不可能的。如果您希望看到Microsoft提供的此类支持,您可能需要考虑在https://connect.microsoft.com/VisualStudio/feedback/details/526307/add-automatic-generation-of-interface-implementation-via-implementing-member投票

答案 2 :(得分:7)

我想我写的是一个可以做你想要的库......它叫做DynamicWrapper(在CodePlex上),它会自动换一个类,所以它实现了一个接口。 Is this what you want?

答案 3 :(得分:3)

显式转换,asis失败,因为类型比较会针对您的代理基类,但隐式转换可以触发DynamicObject.TryConvert,这样您就可以返回内部对象in-lieu动态对象   - TryConvert MSDN Documentation

虽然下面的代码有效,但这不是接口委托本身,只是内部状态的暴露。听起来你可能正在寻找类似拦截模式的东西,比如Brian的DynamicWrapper。

dynamic wrapper = new Proxy(new Foo());
IFoo foo = wrapper;
foo.Bar();

class Proxy : DynamicObject
{
    ...

    public override bool TryConvert(ConvertBinder binder, out object result)
    {
        Type bindingType = binder.Type;
        if (bindingType.IsInstanceOfType(target))
        {
            result = target;
            return true;
        }
        result = null;
        return false;

    }

}

答案 4 :(得分:2)

补充@jbtule的答案我创建了我的CustomActivator,它能够在运行时创建一个动态对象并使其实现所需的接口。我还使用Impromptu-Interface framework来实现这一点。

电话很简单:

CustomActivator.CreateInstance<MyInterface>();

我把它放在github上。