在运行时为接口创建类(C#)
我正在考虑获取一组对象,假设目前有 3 个对象处于活动状态,它们都实现了一个公共接口,然后将这些对象包装在第四个对象中,也实现了相同的接口。
第四个对象的方法和属性的实现将简单地调用这 3 个底层对象上的相关位。 我知道在某些情况下这样做是没有意义的,但这是针对服务多播架构的,因此已经存在一组很好的限制。
我的问题是从哪里开始。 第四个对象的生成应该在运行时在内存中完成,所以我在考虑Reflection.Emit,不幸的是我没有足够的经验,甚至不知道从哪里开始。
我必须构建内存中程序集吗? 看起来确实是这样,但我只是想要一个快速指示我应该从哪里开始。
基本上,我正在考虑采用一个接口,以及全部实现该接口的对象实例列表,并构造一个新对象,还实现该接口,这应该“多播”所有方法调用和对所有底层对象的属性访问,位于尽可能少。 会有很多异常等问题,但当我遇到这些问题时我会解决这些问题。
这是面向服务的体系结构,我希望现有的代码以记录器服务为例,现在可以访问多个记录器服务,而不必更改使用这些服务的代码。 相反,我想在运行时生成一个记录器服务包装器,它在内部简单地调用多个底层对象上的相关方法。
这是针对 .NET 3.5 和 C# 的。
I'm looking at taking a set of objects, let's say there's 3 objects alive at the moment, which all implement a common interface, and then wrap those objects inside a fourth object, also implementing the same interface.
The fourth object's implementations of methods and properties would simply call the relevant bits on those 3 underlying objects. I know that there will be cases here where it won't make sense to do that, but this is for a service multicast architecture so there's already a good set of limitations in place.
My question is where to start. The generation of that fourth object should be done in memory, at runtime, so I'm thinking Reflection.Emit
, unfortunately I don't have enough experience with that to even know where to begin.
Do I have to construct an in-memory assembly? It sure looks that way, but I'd just like a quick pointer to where I should start.
Basically I'm looking at taking an interface, and a list of object instances all implementing that interface, and constructing a new object, also implementing that interface, which should "multicast" all method calls and property access to all the underlying objects, at least as much as possible. There will be heaps of problems with exceptions and such but I'll tackle those bits when I get to them.
This is for a service-oriented architecture, where I would like to have existing code that takes, as an example, a logger-service, to now access multiple logger services, without having to change the code that uses the services. Instead, I'd like to runtime-generate a logger-service-wrapper that internally simply calls the relevant methods on multiple underlying objects.
This is for .NET 3.5 and C#.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您真的需要在运行时创建程序集吗?
也许你不需要它。
c# 为您提供 Action、is 运算符和 lambda/delegates...
Did you really need to create the assembly at runtime?
Probably you don't need it.
c# give you Action<T>, the is operator and lambda/delegates...
如果有人感兴趣,我将在这里发布我自己的实现。
这深受我接受的马克答案的影响和复制。
该代码可用于包装一组对象,所有对象都实现一个公共接口,在一个新对象内,也实现所述接口。 当访问返回对象上的方法和属性时,将以相同的方式访问底层对象上相应的方法和属性。
这里有龙:这是针对特定用途的。 这可能会出现奇怪的问题,特别是因为代码不能确保所有底层对象都被赋予与被调用者传递的完全相同的对象(或者更确切地说,它不会禁止底层对象之一弄乱参数) ,对于有返回值的方法,只会返回最后一个返回值。 至于 out/ref 参数,我什至没有测试过它是如何工作的,但它可能不会。 您已收到警告。
I'll post my own implementation here, if anyone's interested.
This is heavily influenced and copied from Marc's answer, which I accepted.
The code can be used to wrap a set of objects, all implementing a common interface, inside a new object, also implementing said interface. When methods and properties on the returned object is accessed, the corresponding methods and properties on the underlying objects are accessed in the same way.
Here there be dragons: This is for a specific usage. There's potential for odd problems with this, in particular since the code does not ensure that all underlying objects are given the exact same objects as the callee is passing (or rather, it does not prohibit one of the underlying objects from messing with the arguments), and for methods that returns a value, only the last return value will be returned. As for out/ref arguments, I haven't even tested how that works, but it probably doesn't. You have been warned.
(我通过添加额外的上下文/信息来证明答案的合理性)
是的,目前
Reflection.Emit
是解决此问题的唯一方法。在 .NET 4.0 中,
Expression
类已扩展为支持循环和语句块,因此对于单一方法使用,编译后的Expression
将是个好主意。 但即使这样也不支持多方法接口(仅支持单方法委托)。幸运的是,我以前已经这样做过; 请参阅如何用 C# 编写实现给定接口的通用容器类?
(I'm justifying an answer here by adding extra context/info)
Yes, at the moment
Reflection.Emit
is the only way to solve this.In .NET 4.0, the
Expression
class has been extended to support both loops and statement blocks, so for single method usage, a compiledExpression
would be a good idea. But even this won't support multi-method interfaces (just single-method delegates).Fortunately, I've done this previously; see How can I write a generic container class that implements a given interface in C#?