В настоящее время я разрабатываю API, который динамически компилируется в сборку на основе некоторых предопределенных правил, хранящихся в XML-документах.
Мне сложно заставить CodeDOM генерировать свойства с помощью общедоступного получателя и частного установщика, украшенного настраиваемыми атрибутами.
Вот что мне нужно:
[Conditional()]
public E3477 E3477 { get; private set; }
Но я получаю это, что нехорошо, так как я не хочу, чтобы сеттер был открыт публично:
[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();
}
}
CSharpCodeProvider
, как в моем ответе. Это позволит вам создать строку с желаемым исходным кодом C # и просто динамически ее компилировать. - person Konrad Kokosa   schedule 04.07.2014