ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – 实例方法的’this’参数可以是无类型的(即System.Object)吗?

2019-06-21 11:53:06  阅读:236  来源: 互联网

标签:c cil reflection-emit


我正在使用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表达式,它接受输入对象,执行运行时强制转换为目标类型,然后继续调用目标方法.它有效,但我觉得在中间有这个kludge感到不安.

问题是:我可以以某种方式更改我发出的方法,以便他们的这个参数将接受任何System.Object并仍然保持我的发出代码可验证?

如果没有,我想我仍然可以通过使方法静态并在其体中执行转换来避免中间lambda.然而,理想情况下,我想完全避免投射,但我怀疑由于CIL验证和元数据加载的工作方式,这在受管理的世界中无法忍受.

只是想知道是否有更多了解CIL的人可以就这个问题给我建议.谢谢!

更新:我正在努力解决的问题

类具有属性,通常由字段支持.如果期望所述类的实例一次仅维持单个状态,则这很好.对于状态,我指的是在给定时间实例字段中的值的组合.

我的业务需求是为普通字段实现替代存储,这将使单个类实例同时具有多个状态.此要求的一个目标是使其尽可能高效,包括访问的内存和速度.

我的方法背后的核心思想是使用System.Reflection.Emit创建业务类的镜像,并让业务类维护一组这些实例,每个实例对应一个给定的状态.然后,业务类的getter和setter自然必须连接到状态实例上的适当方法.涉及的细节更多,但这是核心理念.

我希望这个解释有助于理解我提出这个问题的原因.我很欣赏它似乎对许多人来说过度工程,但其他不涉及System.Reflection.Emit的替代方案只是过于缓慢和资源匮乏.我不能那样.

解决方法:

您不需要在委托签名中表示“this”类型.

这是一个委托定义,如下所示:

public delegate bool TryGetter<T>(out T value);

形式的任何变量:

TryGetter<T> x;

可以持有:

>类型R上的实例方法,带有签名bool Foo(out T value),以及类型为R的对象实例.
>带有签名静态bool Foo的静态方法(输出T值)
>给定类型为R的对象实例的带有签名静态bool Foo(R对象,out T值)的静态方法.

第三种形式称为委托currying,并允许具有N 1个参数的静态方法表现得好像它是具有N个参数的实例方法(但是只有第一个参数可以被curry).

所以,你想要的界面是:

var instance = InstanceFactory.CreateInstance();
var tryGetName = InstanceFactory.CreateTryGetter<string>(instance,"Name");

然后你可以这样做:tryGetName()返回值.

您可能想要使用案例#3,在其中使用签名bool TryGetWhatEver(TheTypeOfInstance obj,out WhatEver x)生成DynamicMethod,然后创建TryGetter< WhatEver>.

但是我仍然很好奇为什么你需要这样做.除非你动态生成应用程序的大块(如rails),否则这看起来会过于复杂.

标签:c,cil,reflection-emit
来源: https://codeday.me/bug/20190621/1255060.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有