在我们的产品中,我们有称为“服务”的东西,它们是产品不同部分之间(尤其是语言之间——内部语言、C、Python 和 .NET)之间的基本通信方式。
目前代码是这样的(Services.Execute
utilizing params object[] args
):
myString = (string)Services.Execute("service_name", arg1, arg2, ...);
我宁愿能够编写这样的代码并获得类型检查和更简洁代码的好处:
myString = ServiceName(arg1, arg2, ...);
这可以通过一个简单的函数来实现,
public static string ServiceName(int arg1, Entity arg2, ...)
{
return (string)Services.Execute("service_name", arg1, arg2, ...);
}
但这相当冗长,并且在为大量服务执行此操作时并不像我打算做的那样容易管理。
看到 extern
和 DllImportAttribute
是如何工作的,我希望可以通过这样的方式将其连接起来:
[ServiceImport("service_name")]
public static extern string ServiceName(int arg1, Entity arg2, ...);
但我根本不知道如何实现这一点,而且似乎找不到任何相关文档(extern
似乎是一个定义相当模糊的问题)。我发现的最接近的是一个有点相关的问题,How to provide custom implementation for extern methods in .NET?无论如何,这并没有真正回答我的问题,而且有些不同。 C# 语言规范(尤其是在版本 4.0 中,第 10.6.7 节,外部方法)没有帮助。
因此,我想提供外部方法的自定义实现;这可以实现吗?如果是这样,怎么做到的?
最佳答案
C# extern 关键字做的很少,它只是告诉编译器方法声明不会有主体。编译器会进行最低限度的检查,它坚持要求您也提供一个属性,任何事情都会发生。所以这个示例代码将编译得很好:
class Program {
static void Main(string[] args) {
foo();
}
class FooBar : Attribute { }
[FooBar]
static extern void foo();
}
但它当然不会运行,抖动在声明中举起手来。这是实际运行这段代码所需要的,抖动的工作就是为此生成适当的可执行代码。所需要的是抖动识别该属性。
您可以在 SSCLI20 distribution 中抖动的源代码中看到这一点。 , clr/src/md/compiler/custattr.cpp源码文件,RegMeta::_HandleKnownCustomAttribute()函数。这是适用于 .NET 2.0 的代码,我不知道它的添加会影响方法调用。您将看到它处理以下与方法调用的代码生成相关的属性,这些属性将使用 extern 关键字:
[DllImport],你肯定知道
[MethodImpl(MethodImplOptions.InternalCall)],一种在 CLR 而不是框架中实现的方法上使用的属性。它们是用 C++ 编写的,CLR 有一个链接到 C++ 函数的内部表。一个典型的例子是 Math.Pow() 方法,我在 this answer 中描述了实现细节。 .该表不能以其他方式扩展,它在 CLR 源代码中是硬烘焙的
[ComImport],一种将接口(interface)标记为在别处实现的属性,总是在 COM 服务器中实现。您很少直接对该属性进行编程,而是使用由 Tlbimp.exe 生成的互操作库。此属性还需要 [Guid] 属性来提供接口(interface)所需的 guid。这在其他方面类似于 [DllImport] 属性,它生成对非托管代码的 pinvoke 类调用,但使用 COM 调用约定。这当然只有在您的机器上确实有所需的 COM 服务器时才能正常工作,否则它可以无限扩展。
在此函数中可以识别更多属性,但它们与调用别处定义的代码无关。
因此,除非您编写自己的抖动,否则使用 extern 并不是获得所需内容的可行方法。如果您无论如何都想追求这个,您可以考虑 Mono 项目。
纯托管的常见可扩展性解决方案是基本上被遗忘的 System.AddIn 命名空间、非常流行的 MEF 框架和 AOP 解决方案(如 Postsharp)。
关于c# - 我怎样才能实现我自己的外部类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13736156/