gpt4 book ai didi

c# - 使用 CodeDOM 生成私有(private) setter

转载 作者:行者123 更新时间:2023-11-30 13:06:19 26 4
gpt4 key购买 nike

我目前正在开发一种 API,它根据存储在 XML 文档中的一些预定义规则动态编译成程序集。

我很难尝试让 CodeDOM 使用装饰有自定义属性的公共(public) getter 和私有(private) setter 生成属性。

这就是我想要的:

[Conditional()]
public E3477 E3477 { get; private set; }

但是我得到了这个,这不好,因为我不希望 setter 公开暴露:

[Conditional()]
public E3477 E3477
{
get
{
}
set
{
}
}

这是我使用的代码:

var componentRef = string.Format( "E{0}", component.XPathSelectElement( "Element" ).Value );
CodeMemberProperty prop = new CodeMemberProperty();
prop.Name = componentRef;
prop.Type = new CodeTypeReference( componentRef );
prop.HasSet = true;
prop.HasGet = true;
prop.Attributes = MemberAttributes.Public;
CodeAttributeDeclaration conditionalAttr = new CodeAttributeDeclaration( "Conditional" );
prop.CustomAttributes.Add( conditionalAttr );

compositeElementClass.Members.Add( prop );

我所追求的在 CodeDOM 中是否可行?

Stack Overflow 上的社区告诉我使用 CodeDom 并创建程序集而不是使用 MSBuild,我最初尝试这样做但无法让它工作。

** 使用难以阅读的代码进行编辑以查看是否可以简化 **

string GenerateDataElementsCode()
{
CodeNamespace globalNamespace = new CodeNamespace();
globalNamespace.Imports.Add( new CodeNamespaceImport( string.Format( "{0}.DataElements", _project.Target.RootNamespace ) ) );

CodeCompileUnit unit = new CodeCompileUnit();

unit.Namespaces.Add( globalNamespace );

CodeNamespace ns = new CodeNamespace( string.Format( "{0}.DataElements", _project.Target.RootNamespace ) );

var codesDoc = XDocument.Load( string.Format( @"{0}\{1}", _project.Source.RootPath, _project.Source.UNCL ) );

var doc = XDocument.Load( string.Format( @"{0}\{1}", _project.Source.RootPath, _project.Source.EDED ) );
foreach ( XNode node in doc.Descendants( "DataElement" ) )
{
CodeTypeDeclaration dataElementClass = new CodeTypeDeclaration()
{
Name = string.Format( "E{0}", node.XPathSelectElement( "Identifier" ).Value ),
IsClass = true
};

dataElementClass.Comments.Add( new CodeCommentStatement( node.XPathSelectElement( "Description" ).Value, true ) );

dataElementClass.BaseTypes.Add( "SimpleObject" );

CodeAttributeDeclaration dataElementAttr = new CodeAttributeDeclaration( "DataElement" );
dataElementAttr.Arguments.Add(
new CodeAttributeArgument
{
Name = "",
Value = new CodePrimitiveExpression( node.XPathSelectElement( "Identifier" ).Value )
} );
dataElementAttr.Arguments.Add(
new CodeAttributeArgument
{
Name = "",
Value = new CodePrimitiveExpression( node.XPathSelectElement( "Name" ).Value )
} );
dataElementAttr.Arguments.Add(
new CodeAttributeArgument
{
Name = "",
Value = new CodePrimitiveExpression( node.XPathSelectElement( "Description" ).Value )
} );

CodeAttributeDeclaration dataElementFormatAttr = new CodeAttributeDeclaration( "DataElementFormat" );
dataElementFormatAttr.Arguments.Add(
new CodeAttributeArgument
{
Name = "Cardinality",
Value = new CodePrimitiveExpression( node.XPathSelectElement( "Cardinality" ).Value )
} );

dataElementClass.CustomAttributes.Add( dataElementAttr );
dataElementClass.CustomAttributes.Add( dataElementFormatAttr );

var codes = codesDoc.XPathSelectElements( "SimpleDataElements/SimpleDataElement/CodeLists/CodeList" ).Where( a => a.XPathSelectElement( "../../Code" ).Value == node.XPathSelectElement( "Identifier" ).Value );

if ( codes.Count() > 0 )
{

CodeTypeDeclaration codesClass = new CodeTypeDeclaration( "Codes" );
codesClass.Attributes = MemberAttributes.Static;
codesClass.IsClass = true;

foreach ( XNode codeNode in codes )
{
CodeMemberField con = new CodeMemberField( typeof( string ), string.Format( "Code{0}", codeNode.XPathSelectElement( "Code" ).Value ) );
con.Attributes = MemberAttributes.Public | MemberAttributes.Const;
con.InitExpression = new CodePrimitiveExpression( codeNode.XPathSelectElement( "Code" ).Value );

con.Comments.Add( new CodeCommentStatement( codeNode.XPathSelectElement( "Description" ).Value, true ) );

codesClass.Members.Add( con );
}

dataElementClass.Members.Add( codesClass );

}

ns.Types.Add( dataElementClass );

}

unit.Namespaces.Add( ns );

var provider = new Microsoft.CSharp.CSharpCodeProvider();

using ( var sourceCode = new StringWriter() )
using ( var indentedTextWriter = new IndentedTextWriter( sourceCode, " " ) )
{
// Generate source code using the code provider.
provider.GenerateCodeFromCompileUnit( unit,
indentedTextWriter,
new CodeGeneratorOptions() { BracingStyle = "C" } );

return sourceCode.GetStringBuilder().ToString();
}
}

最佳答案

正如其他人指出的那样,CodeDom 本身不支持私有(private) setter (IIRC,因为它不是一个适用于 CodeDom 提供的所有语言的概念)。

大多数解决方案建议将“{ get; private set; }”显式硬编码到片段表达式中,但如果您需要具有逻辑访问器,这并没有多大帮助。这是一种相关但不同的方法,可以让我解决类似的问题。它不是很漂亮,但可以解决问题:

给出了一些辅助类

public static class SnippetGenerator
{
private static CodeDomProvider codeGenProvider = CodeDomProvider.CreateProvider("CSharp");
private static CodeGeneratorOptions codeGenOptions = new CodeGeneratorOptions() { BracingStyle = "C", BlankLinesBetweenMembers = false };
private static StringWriter stringWriter = new StringWriter();

public static string GenerateSnippet(CodeTypeMember member)
{
codeGenProvider.GenerateCodeFromMember(member, stringWriter, codeGenOptions);
string snippet = stringWriter.ToString();
stringWriter.GetStringBuilder().Length = 0;
return snippet;
}
}

然后您可以将现有的 CodeDom 属性转换为您可以使用字符串操作进行后处理的片段:

CodeMemberProperty componentProperty = new CodeMemberProperty();
... //(build out your property)

// inject private scope onto setter
string propertySnippet = SnippetGenerator.GenerateSnippet(componentProperty);
propertySnippet = propertySnippet.Replace(" set\r\n", " private set\r\n");
CodeSnippetTypeMember propertySnippetMember = new CodeSnippetTypeMember(propertySnippet);

注意:可能有比包含“\r\n”(根据您的代/平台设置可能有所不同)更好的方法来删除集合,但这是确保它不是的简单方法抓取任何不正确的子字符串。选择最适合您项目的方式。

关于c# - 使用 CodeDOM 生成私有(private) setter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24576062/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com