方法名称中的连字符,是否可以在任何.NET语言中使用?

时间:2010-01-14 02:33:10

标签: .net clr xslcompiledtransform

我需要支持名为'send-request'的方法作为在XSLT转换中使用的扩展函数。这是由XslCompiledTransform上的扩展程序对象提供的。扩展对象与<msxsl:script>的关系很酷,我不必使用<msxsl:script>,只需声明命名空间并调用函数即可。不好的是,函数名称必须与CIL方法名称完全匹配。

所以,我想知道,是否有一种.NET语言支持方法名称中的连字符?不需要CLS合规性,使用反射调用该方法。

或者,我可以使用一些修改程序集IL的技术来更改方法名称吗?

或者,有没有办法拦截反射GetMethod调用并欺骗调用方存在方法'send-request',而是返回'SendRequest'方法呢?

4 个答案:

答案 0 :(得分:6)

您可以使用反射来完成此操作。

我使用ILAsm将以下内容汇编成一个程序集(我删除了实际编译所需的所有漏洞;这些只是显着位(双关语)):

.method private hidebysig static int32 
'Te-st'() cil managed {
    // Code size       8 (0x8)
    .maxstack  1
    .locals init ([0] int32 CS$1$0000)
    IL_0000:  nop
    IL_0001:  ldc.i4.s 0x11
    IL_0002:  stloc.0
    IL_0003:  br.s       IL_0005

    IL_0005:  ldloc.0
    IL_0006:  ret
}

我在名为Program的名称空间中名为Test的类中定义了此方法。请注意,方法名称由单引号括起。这是根据规范(ECMA#335):

  

标识符用于命名实体。简单标识符等同于ID。但是,ILAsm语法   允许使用可以使用Unicode字符集形成的任何标识符(请参阅分区I)。 实现   这样,标识符应放在单引号内。

然后:

var assembly = Assembly.LoadFrom(path);
var method = assembly.GetType("Test.Program")
                     .GetMethod(
                         "Te-st",
                         BindingFlags.Static | BindingFlags.NonPublic
             );
Console.WriteLine(method.Invoke(null, null));

这产生了输出:

17

我怀疑通常的.NET语言是否可行。我不知道任何允许/要求您“转义”标识符的语言。没有它,你能想象试图消除以下的歧义:

int a;
int b;
int a-b;
int diff = a-b; // is that a minus b or the variable a-b?

也许有一个COBOL.NET你可以做到这一点,我不知道。

答案 1 :(得分:1)

标识符名称中的连字符在Lisp和Scheme中非常常见,因此我怀疑它至少在IronScheme中被本地支持。在Ruby中创建这样的方法也很容易,尽管事实上在Ruby标识符中实际上是非法的,所以你可以使用IronRuby

此外,C#中的@ escape-thingy允许您使用其他非法标识符,但我无法弄清楚如何在这种情况下使用它。

答案 2 :(得分:0)

我认为你能做的最简单的事就是直接在IL中定义方法。首先定义一个抽象类,它包含您想要的所有其他方法。然后在IL中定义一个包含连字符方法名称的派生类,并将其编译到一个单独的库中。

答案 3 :(得分:0)

我有理由相信CLR语言规范的一部分是它们必须能够处理运行时支持的任何名称,即使它恰好是该语言中的保留关键字或其他非法。

假设是这种情况,如果运行时支持方法名称中的连字符,那么所有CLR语言都应该能够处理它们,即使它需要像VB.NET的[]语法用于声明或使用它们。