【发布时间】:2011-04-26 13:43:36
【问题描述】:
我正在使用System.Reflection.Emit 的TypeBuilder 发出一堆带有实例方法的自定义.NET 类。例如:
public class EmittedClass
{
public bool TryGetName(out string value)
{
...
}
public bool TryGetAge(out int value)
{
...
}
}
所有方法都遵循可以由通用委托描述的相同签名:
public delegate bool TryGetter<T>(out T value);
当然,我希望能够在调用站点上明确指定目标实例,如下所示:
var instance = InstanceFactory.CreateInstance();
var tryGetName = InstanceFactory.CreateTryGetter<string>("Name");
string name;
if (tryGetName(instance, out name)) // Problem here.
{
...
}
为此,我需要将委托变成所谓的开放委托:
public delegate bool TryGetter<T>(object instance, out T value);
由于我没有目标实例的编译时类型,我需要将其传递为System.Object。但是,这在运行时会中断,因为实例方法期望它的“this”是声明类的类型。哎哟。
我目前使用的解决方案是创建一个中间 lambda 表达式,该表达式接受输入对象,执行运行时转换为目标类型,然后继续调用目标方法。它有效,但我对中间有这个杂物感到不安。
问题是:我能否以某种方式更改我发出的方法,以便它们的 this 参数将接受任何 System.Object 并仍然保持我发出的代码可验证?
如果不是,我想我仍然可以通过将方法设为静态并在它们的主体中执行强制转换来避免中间 lambda。但是,理想情况下,我想完全避免强制转换,但我怀疑由于 CIL 验证和元数据加载的工作方式,这在托管世界中是站不住脚的。
只是想知道是否有更了解 CIL 的人可以就这个主题给我建议。谢谢!
更新:我要解决的问题
类具有属性,通常由字段支持。这很好,如果期望所述类的实例一次只保持一个状态。状态是指给定时间实例字段中值的组合。
我的业务需求是为普通字段实现一种替代存储,这将使单个类实例能够同时具有多个状态。此要求的一个附带目标是使其尽可能高效,无论是内存还是访问速度。
我的方法背后的核心思想是使用System.Reflection.Emit 创建业务类的镜像,并让业务类维护一组这些实例,每个实例对应于一个给定的状态。业务类的 getter 和 setter 自然必须连接到状态实例上的适当方法。涉及的细节很多,但这是核心思想。
我希望解释有助于理解我提出这个问题的原因。我很欣赏这对许多人来说似乎是过度设计,但其他不涉及System.Reflection.Emit 的替代方案实在是太慢了,而且资源匮乏。我不能拥有那个。
【问题讨论】:
-
我认为您正在做一些非常有趣的事情。但是,您是在向后问问题。恕我直言,与其询问是否可以制定一个糟糕的解决方案,不如寻求一个好的解决方案会产生更多有用的回应
-
点了。我没有解释问题,我正在努力解决。我会更新我的问题。
-
回应您的编辑:您的实际业务问题是什么?为什么需要一个对象同时具有两种状态 - 为什么不是两个不同的对象?
-
@Dan:嗯,它们是两个不同的对象,不是吗?一个是业务对象,另一个是状态对象。但我知道你的意思。 :) 部分原因是业务对象还具有与状态管理无关的其他属性(更不用说很多方法)。为此,简单地为状态重用相同的类不是一种选择。第二个原因是业务对象的消费者不应该被多个对象所负担。这对他来说真的只是一个对象。最后一部分原因是为了避免手动样板代码。
-
@aoven:您在编辑中说过“我的业务需求是实现一种替代存储来替代普通字段,这将使单个类实例能够同时具有多个状态。”这不是业务需求,而是针对业务需求的技术解决方案。我无法想象有理由更喜欢大量
System.Reflection.Emit代码而不是任何数量的样板代码 - 你确定这是正确的答案吗?
标签: c# cil reflection.emit