正在使用CodeDOM创建扩展方法
本文关键字:创建 扩展 方法 CodeDOM | 更新日期: 2023-09-27 17:59:03
我正在尝试使用CodeDOM创建一个扩展方法。似乎没有任何对它们的支持,并且不允许使用ExtensionAttribute
(C#在内部使用它来标记扩展方法)。
可以使用一个技巧来指定this
修饰符,但是我如何使包含类static
,以便代码真正编译呢?
由于static
是一个C#概念,因此它不会通过CodeDOM API公开。将TypeAttributes
设置为TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.Public
不起作用,因为
抽象类不能被密封或静态
如何使扩展方法进行编译?
我很确定您正在寻找:
var staticClass = new CodeTypeDeclaration("Extensions")
{
Attributes = MemberAttributes.Public|MemberAttributes.Static
};
然而,这似乎并不奏效。有趣的是:
provider.Supports(GeneratorSupport.StaticConstructors);
// True
provider.Supports(GeneratorSupport.PublicStaticMembers);
// True
但是,当您去输出它时,即使Attributes属性明显从0x00005002
更改为0x00006003
,也不会发生任何更改。
根据Microsoft Connect,这是不可能的:
感谢您的报道。不幸的是,我们似乎无法支持CodeDom的静态类。
原因是CodeDom的设计目标之一是独立于语言,这样为一种语言生成的任何代码都可以很容易地为另一种语言产生。虽然C#中经常使用静态类,但VB并不支持它们。因此,添加对静态类的支持将意味着一些可以为C#编译的代码将无法为VB编译,这与我们的目标背道而驰。
虽然我们无法对此问题采取行动,但我们要求您在未来继续提供反馈,以帮助我们改进。
一个肮脏的解决方法:
var type = new CodeTypeDeclaration("Extensions");
type.Attributes = MemberAttributes.Public;
type.StartDirectives.Add(
new CodeRegionDirective(CodeRegionMode.Start, "'nstatic"));
type.EndDirectives.Add(
new CodeRegionDirective(CodeRegionMode.End, String.Empty));
产品:
#region
static
public class Extensions
{
}
#endregion
它编译。
您可以获得源代码,用static class Extensions
替换class Extensions
并编译该代码,而不是直接编译CodeCompileUnit
。
稍微清理了sixtlettervariables提供的破解:将其放入静态方法中,如讨论中所述。
public static void MarkAsStaticClassWithExtensionMethods(this CodeTypeDeclaration class_)
{
class_.Attributes = MemberAttributes.Public;
class_.StartDirectives.Add(new CodeRegionDirective(
CodeRegionMode.Start, Environment.NewLine + "'tstatic"));
class_.EndDirectives.Add(new CodeRegionDirective(
CodeRegionMode.End, string.Empty));
}
您可以直接将代码转换为字符串,然后对其进行黑客攻击,从而使代码按照您的意愿进行编译:
private static CodeSnippetTypeMember CreateStaticClass(CodeTypeDeclaration type)
{
var provider = CodeDomProvider.CreateProvider("CSharp");
using (var sourceWriter = new StringWriter())
using (var tabbedWriter = new IndentedTextWriter(sourceWriter, "'t"))
{
tabbedWriter.Indent = 2;
provider.GenerateCodeFromType(type, tabbedWriter, new CodeGeneratorOptions()
{
BracingStyle = "C",
IndentString = "'t"
});
return new CodeSnippetTypeMember("'t't" + sourceWriter.ToString().Replace("public class", "public static class"));
}
}