EntityFramework t4 template - XML documentation

柔情痞子 提交于 2019-12-06 13:14:35

It does appear that entity framework isn't going to generate the objects for you with code documentation, and I cant see a solution on nuget, which is a shame.

You can modify the T4 template to do this for you without too much hassle. To Get you started, if you open the T4 template for your entities, and find the line that looks like this (about line 74 for me):

    <#=codeStringGenerator.Property(edmProperty)#>

Then change it to something like this:

<# if (edmProperty != null && edmProperty.Documentation != null) {#>
/// <summary>
/// <#= edmProperty.Documentation.Summary #>
/// </summary>
/// <remarks>
/// <#= edmProperty.Documentation.LongDescription #>
/// </remarks>
<# } #>
    <#=codeStringGenerator.Property(edmProperty)#>

This will generate the documentation for your properties.

And also if you go to the line that looks like this (about line 28 for me):

<#=codeStringGenerator.EntityClassOpening(entity)#>

Then change it to something like this:

<# if (entity != null && entity.Documentation != null) {#>
/// <summary>
/// <#= entity.Documentation.Summary #>
/// </summary>
/// <remarks>
/// <#= entity.Documentation.LongDescription #>
/// </remarks>
<# } #>
<#=codeStringGenerator.EntityClassOpening(entity)#>

This should give you your class documentation.

There's probably a few other places that will need updating (like complex and navigation properties), but it should get you most of the way.

Matt

Here's my take on this.

In the generated CodeStringGenerator class in your .tt file, I added this method:

private string Comments(EdmMember member)
{
    string comments = member.Documentation != null
        ? (string.IsNullOrEmpty(member.Documentation.Summary)
            ? ""
            : @"
/// <summary>
/// " + member.Documentation.Summary.Replace("\n", Environment.NewLine + "    /// ") + @" 
/// </summary>
")
            +
            (string.IsNullOrEmpty(member.Documentation.LongDescription)
            ? ""
            : @"/// <remarks>
/// " + member.Documentation.LongDescription.Replace("\n", Environment.NewLine + "    /// ") + @"
/// </remarks>
")
        : "";
    return comments;
}

I admit this method has two problems: a) it assumes a certain level of indentation, although this is the expected indentation level for a property, b) if there is no Summary, an extra line is added before the comment. But this is unlikely to happen.

Then, I call this method from the method that generate simple and navigation properties:

public string Property(EdmProperty edmProperty)
{
    string comments = Comments(edmProperty);
    return string.Format(
        CultureInfo.InvariantCulture,
        @"{5}{0} {1} {2} {{ {3}get; {4}set; }}",
        Accessibility.ForProperty(edmProperty),
        _typeMapper.GetTypeName(edmProperty.TypeUsage),
        _code.Escape(edmProperty),
        _code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
        _code.SpaceAfter(Accessibility.ForSetter(edmProperty)),
        comments);
}

public string NavigationProperty(NavigationProperty navProp)
{
    string comments = Comments(navProp);
    var endType = _typeMapper.GetTypeName(navProp.ToEndMember.GetEntityType());
    return string.Format(
        CultureInfo.InvariantCulture,
        "{5}{0} {1} {2} {{ {3}get; {4}set; }}",
        AccessibilityAndVirtual(Accessibility.ForNavigationProperty(navProp)),
        navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
        _code.Escape(navProp),
        _code.SpaceAfter(Accessibility.ForGetter(navProp)),
        _code.SpaceAfter(Accessibility.ForSetter(navProp)),
        comments);
}

I'd like to add more details to Matt Mhetton's answer because because of my current project configuration (CA and Style cop) everything MUST be documented..

On the one hand you will have to add documentation properties in the designer for everything you want to document (classes, simple properties, complex properties and navigation properties)

On the other hand you have to open WhateverModel.tt you havecreated and edit it to contain documentation, I explain it step by step:

1.- For class documentation, look for:

<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
<#=codeStringGenerator.EntityClassOpening(entity)#>

(line 26 in my case) and place your comments just between those two lines like this:

<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
<# if (entity != null && entity.Documentation != null) {#>
/// <summary>
/// <#= entity.Documentation.Summary #>
/// </summary>
<# } #>
<#=codeStringGenerator.EntityClassOpening(entity)#>

2.- For constructor documentation look for public <#=code.Escape(entity)#>() thaqt's what generates the constructor so place your documentation just before that line like this:

<# if (entity != null && entity.Documentation != null) {#>
    /// <summary>
    /// <#= entity.Documentation.Summary #>
    /// </summary>
<# } #>
    public <#=code.Escape(entity)#>()
    {

3.- To document every property look for foreach (var edmProperty in simpleProperties), this look is the one that will generate properties code so, it should looks like this:

foreach (var edmProperty in simpleProperties)
        {
#>
<# if (edmProperty != null && edmProperty.Documentation != null) {#>    
    /// <summary>
    /// <#= edmProperty.Documentation.Summary #>
    /// </summary>
<# } #>
    <#=codeStringGenerator.Property(edmProperty)#>
<#

        }

(NOTE: that's for simple properties but is going to be3 the same way for complex properties...)

4.- For navigation properties exactly the same, look for foreach (var navigationProperty in navigationProperties) and add your documentation like this:

foreach (var navigationProperty in navigationProperties)
        {
#>
<# if (navigationProperty != null && navigationProperty.Documentation != null) {#>
    /// <summary>
    /// <#= navigationProperty.Documentation.Summary #>
    /// </summary>
<# } #>
    <#=codeStringGenerator.NavigationProperty(navigationProperty)#>
<#

        }

4.- Last but not least, if you also need documentation in your context class you could use this (look for <# if (code.Escape(container) != null) {#> ):

<# if (code.Escape(container) != null) {#>
/// <summary>
/// Represents <#= code.Escape(container) #>
/// </summary>
<# } #>
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{

<# if (code.Escape(container) != null) {#>
    /// <summary>
    /// Initializes a new instance of the <see cref="<#= code.Escape(container) #>"/> class.
    /// </summary>
<# } #>
    public <#=code.Escape(container)#>()
    : base("name=<#=container.Name#>")
    {
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
        this.Configuration.LazyLoadingEnabled = false;
<#
}
#>
    }

    /// <summary>
    /// On Model Creating
    /// </summary>
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

<#
    foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())
    {
#>

   <# if (code.Escape(entitySet) != null) {#>
    /// <summary>
    /// Gets or sets the <#=code.Escape(entitySet)#>
    /// </summary>
    <# } #>

I hope it helps like Matt Whetton's answer helped me (thank you Matt).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!