在 C# 中模拟 IDispatchEx
C# 3.0 扩展方法向基本类型添加扩展,使得在该类型的所有实例上调用该方法都是合法的。
现在,我知道 JavaScript 实现了 IDispatchEx,通过它可以向特定实例添加方法。
那么如何向 C# 类的“实例”添加一组方法呢? 我知道这是动态语言与静态语言的圣战领域。 :) 让我澄清一下我的意图不是这个。
我只是希望能够根据实现该接口的类向接口添加一组事件。
我能够使用泛型做到这一点
inteface ISample<T> { T SupportedEvents; }
class Sample : ISample<UIWidgetEvent> { }
class Sample2 : ISample<NonVisualUIWidget> { }
class UIWidgetEvent { public EventHandler Clicked; }
class NonVisualUIWidget {public EventHandler Expired;}
class TestSample
{
public void Test()
{
new Sample().SupportedEvents.Clicked += ...
new Sample2().SupportedEvents.Expired += ...
}
}
然后我不喜欢 SupportedEvents
我希望能够说
new Sample().Clicked +=...
然后我想到了 JavaScript(我知道 C#
不是 JS
:))... AND IDispatchEx
、IL Weaving
、Reflection.Emit
等等,并且认为可能有一个这样做的方法... [设计时支持会很好,但我可以没有]
是的,我可能可以使用访问者模式来执行此“实例增强”。 [虽然不确定我是否可以获得合成糖]
评论?
C# 3.0 Extension methods add extensions to the base Type making calling that method on all instances of that Type legal.
Now, JavaScript I know implements IDispatchEx through which it's possible to add methods to a specific instance.
So how do I add a set of methods to an 'instance' of a C# class? I know this is a Dynamic vs. Static Languages holy war territory. :) Let me clarify my intention is NOT that.
I just want to be able to add a set of events to an interface depending on the class implementing that interface.
I was able to do that using Generics
inteface ISample<T> { T SupportedEvents; }
class Sample : ISample<UIWidgetEvent> { }
class Sample2 : ISample<NonVisualUIWidget> { }
class UIWidgetEvent { public EventHandler Clicked; }
class NonVisualUIWidget {public EventHandler Expired;}
class TestSample
{
public void Test()
{
new Sample().SupportedEvents.Clicked += ...
new Sample2().SupportedEvents.Expired += ...
}
}
Then I didn't like SupportedEvents
I want to be able to say
new Sample().Clicked +=...
Then I thought JavaScript (I know C#
is not JS
:))... AND IDispatchEx
, IL Weaving
, Reflection.Emit
etc. etc. and thought may be there's a way to do this... [Design time support would be nice but I can live without]
Yes, I probably could do this "instance augmentation" with a Visitor pattern.
[Not sure if I could get the syntatic sugar though]
Comments?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,您可以为“新”方法创建一个 DynamicMethod 实例,但在运行时将它们静态附加到现有实例是行不通的,因为它根本无法编译。
您可能(我还没有尝试过)能够将操作码发送到内存中的程序集中,但这与您所能得到的“语法上的甜蜜”相差甚远(将涉及很多反射和 InvokeMember 调用,我想)
它也可能值得研究扩展方法 - 尽管我从未尝试通过扩展方法附加事件或类似事件的方法......而且它们只是 3.5,因此可能会限制你。
最好看的“纯 C#”实现可能与您已经通过通用/接口设置获得的非常相似...
老实说,如果您正在寻找像这样具有真正“动态支持”的东西,我'使用支持 DLR 的语言(例如 IronPython)执行此类操作,并从 C# 中调用它。
Well, you could create a DynamicMethod instance for your "new" methods, but statically attaching them to an existing instance at runtime wouldn't work due to the fact it plain wouldn't compile.
You might (I haven't tried this) be able to emit the opcodes into an in-memory assembly, but that's about as far away from being "Syntactically sweet" as you can get (would involve a lot of reflection and InvokeMember calls, I would think)
It also might be worth looking into Extension Methods - although I've never tried attaching events or event-like methods via extension methods...and they are 3.5 only, so that may limit you.
The nicest looking, "pure C#" implementation is probably something very similar to what you've already got with the generic/interface setup...
Honestly, if you're looking for something with true "dynamic support" like this, I'd do this kind of stuff in a DLR-capable language (like IronPython) and call into it from your C# stuff.