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?