Writing code generation logic for a property turned out to be a lot of work: first, I had to add declaration for a private backing field, then a property declaration, including code expressions for both getter and setter. Here's sample code similar to what I ended up with:
var myType = new CodeTypeDeclaration("Person");
var field = new CodeMemberField()
{
Name = "_LastName",
Type = new CodeTypeReference("System.String"),
Attributes = MemberAttributes.Private
};
myType.Members.Add(field);
var prop = new CodeMemberProperty()
{
Name = "LastName",
Type = new CodeTypeReference("System.String"),
Attributes = MemberAttributes.Public
};
prop.GetStatements.Add(
new CodeMethodReturnStatement(
new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(), "_LastName")));
prop.SetStatements.Add(
new CodeAssignStatement(
new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(), "_LastName"),
new CodePropertySetValueReferenceExpression()));
myType.Members.Add(prop);
And here is the code that was generated by the above fragment:
private string _LastName;
public string LastName
{
get { return _LastName; }
set { _LastName = value; }
}
Of course, C# 3.0 has introduced a much shorted way of declaring the same property: "public string LastName { get; set; }". This syntax is called "auto-implemented properties" and it puts the burden on the compiler to create a backing field and implement getter and setter logic. Naturally, I wanted generated classes to look cleaner, so being an optimist that I am I decided to change code generation logic to create auto-implemented properties instead.
That proved to be a mistake: after a while I realized that classes in System.CodeDom namespace do not support auto-implemented properties generation. The best I could come up with was a hack using CodeSnippetTypeMember:
var snippet = new CodeSnippetTypeMember("public string LastName { get; set; }");
myType.Members.Add(snippet);
This solution is pretty far from ideal. It goes against the spirit of code generation because it allows me to target just one programming language, C#. Still, it is pragmatic. Hopefully, Microsoft can bring CodeDom up to date in a future release.
2 comments:
Try following
var cfield = new CodeMemberField
{
Attributes = MemberAttributes.Public | MemberAttributes.Final,
Name = MyPropName,
Type = new CodeTypeReference(typeof(MyType)),
};
cfield.Name += " {get;set;}";
dalshe.com
dalshe: your snippet appears to work but doesn't compile due to the invalid semicolons on the field definitions
Post a Comment