我需要支持名为'send-request'的方法作为在XSLT转换中使用的扩展函数。这是由XslCompiledTransform
上的扩展程序对象提供的。扩展对象与<msxsl:script>
的关系很酷,我不必使用<msxsl:script>
,只需声明命名空间并调用函数即可。不好的是,函数名称必须与CIL方法名称完全匹配。
所以,我想知道,是否有一种.NET语言支持方法名称中的连字符?不需要CLS合规性,使用反射调用该方法。
或者,我可以使用一些修改程序集IL的技术来更改方法名称吗?
或者,有没有办法拦截反射GetMethod
调用并欺骗调用方存在方法'send-request',而是返回'SendRequest'方法呢?
答案 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的[]
语法用于声明或使用它们。