使用.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
的内容。
所以,我的问题是:
这实际上可以用动态运行时吗?似乎动态实现方法和属性之类的东西相当容易,但我没有找到任何关于动态实现接口和转换的文档。
假设这是可能的,它有多难? (你可以假设我是一个体面的程序员,拥有丰富的反思经验,但对动态框架不熟悉。)
是否有任何资源可以帮助我指明实现这样的事情的正确方向?或者甚至已经完成这种事情的样本我可以作为一个起点?
答案 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)
显式转换,as
和is
失败,因为类型比较会针对您的代理基类,但隐式转换可以触发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上。