Das Generieren von POCO-Klassen aus dem Entity-Framework Modell klappt ja recht einfach.
Leider werden aber die Beschreibungen nicht als XML-Comments übernommen.
Aber es gibt eine Lösung: einfach die T4-Templates erweitern…
Zum Erstellen der POCO-Klassen und der Context-Klasse (enthält den Datenbank-Zugriff) werden 2 T4-Templates benutzt: z.B. DataModel.tt und DataModel.Context.tt
Durch Ändern dieser Dateien kann die Code-Generierung verändert werden.
Das Extrahieren der Dokumentation aus dem EDMX-Modell ist sehr einfach, leider aber nicht gut dokumentiert. Jedes MetaitemData-Objekt (z.B. der EntityContairner, jedes EntitySet oder jeder EntityType) enthält ein optionales Property 'Documentation'. Hier sind 'Summary' und 'LongDescription' aus dem Modell abgelegt.
folgende Punkte sind zu beachten:
- ist keine Dokumentation im Modell hinterlegt, ist .Documentation null
- Zeilenumbrüche müssen beim Erstellen der XML-Kommentare entsprechend um den Komentar-Prefix ergänzt werden
- die Dokumentation muss XML-Encoded werden (z.B. &, <, >)
Als C#-Beispiel wurden die T4-Templates um folgenden Code ergänzt:
#region XML-Comments private const string XMLCOMMENT_START = "/// "; private static string XmlEntityize(string text) { if (string.IsNullOrEmpty(text)) { return string.Empty; } text = text.Replace("&","&"); text = text.Replace("<","<").Replace(">",">"); string id = Guid.NewGuid().ToString(); text = text.Replace(Environment.NewLine, id); text = text.Replace("r", "
").Replace("n","
"); text = text.Replace(id, Environment.NewLine); return text.Replace("'","'").Replace(""","""); } private static string PrefixLinesOfMultilineComment(string prefix, string comment) { return comment.Replace(Environment.NewLine, Environment.NewLine + prefix); } public static string SummaryCommentElement(MetadataItem item, string defaultComment) { var comment = ((item.Documentation != null) && !string.IsNullOrWhiteSpace(item.Documentation.Summary)) ? item.Documentation.Summary : defaultComment; if (string.IsNullOrWhiteSpace(comment)) return string.Empty; comment = PrefixLinesOfMultilineComment(XMLCOMMENT_START, XmlEntityize(comment)); return string.Format((comment.Contains(Environment.NewLine) ? "{0}<summary>n{0}{1}n{0}</summary>" : "{0}<summary>{1}</summary>"), XMLCOMMENT_START, comment); } public static string LongDescriptionCommentElement(MetadataItem item, int indentLevel) { var comment = ((item.Documentation != null) && !string.IsNullOrWhiteSpace(item.Documentation.LongDescription)) ? item.Documentation.LongDescription : string.Empty; if (string.IsNullOrWhiteSpace(comment)) return string.Empty; comment = PrefixLinesOfMultilineComment(XMLCOMMENT_START, XmlEntityize(comment)); return string.Format((comment.Contains(Environment.NewLine) ? "n{0}<LongDescription>n{0}{1}n{0}</LongDescription>" : "n{0}<LongDescription>{1}</LongDescription>"), XMLCOMMENT_START, comment); } public static string ParameterComments(IEnumerable<Tuple<string, string>> parameters, int indentLevel) { System.Text.StringBuilder builder = new System.Text.StringBuilder(); foreach (Tuple<string, string> parameter in parameters) { builder.AppendLine(); builder.Append(CodeRegion.GetIndent(indentLevel)); builder.Append(XMLCOMMENT_START); builder.Append(String.Format(CultureInfo.InvariantCulture, " <param name="{0}">{1}</param>", parameter.Item1, parameter.Item2)); } return builder.ToString(); } #endregion // XML-Comments
Verwendet wird das dann z.B. so:
<#=SummaryCommentElement(entity, "Generated Entity-Class.")#> <#=LongDescriptionCommentElement(entity, region.CurrentIndentLevel)#>
Ist doch cool, oder?