我正在使用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 表达式,该表达式接受输入对象,对其进行运行时转换为目标类型,然后继续调用目标方法。这样做可以解决问题,但是我对在中间添加这个修补程序感到不安。
问题是:是否可以以某种方式更改发出的方法,使其接受任何
System.Object
作为其 'this' 参数,并仍保持我的发出代码可验证?如果不能,我认为仍然可以通过使方法静态化并在它们的主体中执行转换来避免中间 lambda。但是理想情况下,我希望完全避免强制转换,但我怀疑由于 CIL 验证和元数据加载工作的方式,这在托管世界中是无法实现的。
只是想知道对 CIL 更有了解的人能否就此向我提供建议。谢谢!
更新:我要解决的问题
类具有属性,通常由字段支持。如果预计该类的实例仅维护一次状态,则这是可以的。状态指给定时间内实例字段中值的组合。
我的业务需求是实现一个备选存储,以使单个类实例在同一时间具有多个状态。该要求的一个附带目标是尽可能地高效,无论是内存还是访问速度方面。
我方法的核心思想是使用
System.Reflection.Emit
创建业务类的镜像,并使业务类维护一组这些实例,每个实例对应于特定状态。然后,业务类的 getter 和 setter 自然地必须连接到状态实例上的适当方法。涉及更多细节,但这是核心思想。我希望这种解释有助于理解我提出这个问题的原因。我知道这可能看起来过度工程化,但其他不涉及
System.Reflection.Emit
的替代方法太慢且资源占用过高。我不能接受这样的情况。
System.Reflection.Emit
代码而不是任意数量的样板代码-你确定这是正确的答案吗? - Dan Puzey