Добавление пользовательских атрибутов свойств в код Entity Framework - PullRequest
26 голосов
/ 26 июня 2009

Есть ли способ добавить пользовательские атрибуты в свойства в сгенерированном EF-коде? Единственное, что я вижу в качестве правдоподобного решения, - это создать собственный шаблон T4. Однако из-за характера атрибута было бы невозможно определить правильный параметр атрибута для каждого свойства EF.

Ответы [ 6 ]

35 голосов
/ 19 августа 2010

Вы можете сделать это, указав тип метаданных, который отражает свойства и используется просто для указания авторства.

[MetadataType(typeof(Dinner_Validation))] 
public partial class Dinner 
{} 

public class Dinner_Validation 
{ 
    [Required] 
    public string Title { get; set; } 
}

Стив Смит пишет об этом здесь .

К сожалению, вышеупомянутый подход хрупок для рефакторинга. Другой вариант - использовать новые объекты POCO. Насколько я могу судить, они полностью избегают генерации кода во время компиляции. Я еще не использовал их, поэтому не могу комментировать любые подводные камни или компромиссы.

12 голосов
/ 29 октября 2011

Вы можете добавить это в файл EDMX, также с помощью Designer:

<Property Name="Nome" Type="String" Nullable="false" MaxLength="50" Unicode="true" FixedLength="false" >
            <Documentation>
              <Summary>[MyCustomAttribute]</Summary>
            </Documentation>
</Property>

И заменить Т4:

void WriteProperty(CodeGenerationTools code, EdmProperty edmProperty)
{
    WriteProperty(Accessibility.ForProperty(edmProperty),
                  code.Escape(edmProperty.TypeUsage),
                  code.Escape(edmProperty),
                  code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
                  code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
}

С:

void WriteProperty(CodeGenerationTools code, EdmProperty edmProperty)
{
    if(edmProperty.Documentation != null && string.IsNullOrWhiteSpace(edmProperty.Documentation.Summary) == false)
    {
    #>
    <#=edmProperty.Documentation.Summary#>
<#+
    }
    WriteProperty(Accessibility.ForProperty(edmProperty),
                  code.Escape(edmProperty.TypeUsage),
                  code.Escape(edmProperty),
                  code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
                  code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
}
8 голосов
/ 20 октября 2011

Вы можете создать интерфейс и объявить атрибут на интерфейсе.

partial class Person : IPerson {}

public interface IPerson
{
    [Required]
    string Name { get; set; }
}
3 голосов
/ 12 марта 2014

Вы можете добавить это в файл EDMX, также с помощью Designer:

<Property Name="Nome" Type="String" Nullable="false" MaxLength="50" Unicode="true" FixedLength="false" >
            <Documentation>
              <Summary>[MyCustomAttribute]</Summary>
            </Documentation>
</Property>

И заменить Т4:

void WriteProperty(CodeGenerationTools code, EdmProperty edmProperty)
{
    WriteProperty(Accessibility.ForProperty(edmProperty),
                  code.Escape(edmProperty.TypeUsage),
                  code.Escape(edmProperty),
                  code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
                  code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
}

С:

void WriteProperty(CodeGenerationTools code, EdmProperty edmProperty)
{
    if(edmProperty.Documentation != null && string.IsNullOrWhiteSpace(edmProperty.Documentation.Summary) == false)
    {
    #>
    <#=edmProperty.Documentation.Summary#>
<#+
    }
    WriteProperty(Accessibility.ForProperty(edmProperty),
                  code.Escape(edmProperty.TypeUsage),
                  code.Escape(edmProperty),
                  code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
                  code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
}

А для Entity Framework 6 заменить

public string Property(EdmProperty edmProperty)
{
    return string.Format(
        CultureInfo.InvariantCulture,
        "{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)));
}

с

public string Property(EdmProperty edmProperty)
{
    var description = String.Empty;
    bool isAttribute = false;

    if(edmProperty.Documentation != null &&
        string.IsNullOrWhiteSpace(edmProperty.Documentation.Summary) == false)
    {
        string summary = edmProperty.Documentation.Summary;
        if (!String.IsNullOrEmpty(summary) && summary.First() == '[' && summary.Last() == ']')
        {
            isAttribute = true;
        }

        if (isAttribute)
        {
            description = String.Format("\r\n\t{0}\r\n\t", summary);
        }
        else
        {
            description = String.Format("\r\n\t/// <summary>\r\n\t/// {0}\r\n\t/// </summary>\r\n\t", 
                summary);
        }

    }

    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)),
        description);
}

Предупреждения:

  • Пространства имен должны быть решены абсолютно.
  • Предполагается, что атрибуты начинаются с '[' и заканчиваются на ']' - никакой другой проверки ошибок
  • Если открывающая и закрывающая фигурные скобки не найдены, сводная информация о свойствах каркаса сущности оборачивается в тройной слеш-комментарий XML.
  • Попытки сопоставить информацию по стилю визуальной студии по умолчанию (на самом деле это просто отступы), что может или не может иметь место для вашего проекта. Это включает в себя новые строки.

пример вывода:

/// <summary>
/// content type
/// </summary>
public System.Guid ContentType { get; set; }

[System.ComponentModel.DisplayName("Last Modified")]
public System.DateTime LastModified { get; set; }
0 голосов
/ 11 сентября 2015

В дополнение к ответу BurnsBA, чтобы применить это и к свойствам навигации, обновите также NavigationProperty():

public string NavigationProperty(NavigationProperty navProp)
{
    var description = String.Empty;
    if(navProp.Documentation != null && string.IsNullOrWhiteSpace(navProp.Documentation.Summary) == false)
    {
        string summary = navProp.Documentation.Summary;
        if (!String.IsNullOrEmpty(summary) && summary.First() == '[' && summary.Last() == ']')
        {
            description = String.Format("\r\n\t{0}\r\n\t", summary);
        }
        else
        {
            description = String.Format("\r\n\t/// <summary>\r\n\t/// {0}\r\n\t/// </summary>\r\n\t", summary);
        }
    }

    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)),
        description);
}

Я использую это, чтобы добавить [Newtonsoft.Json.JsonIgnore] к моим свойствам.

Примечание: Вы должны добавить их к <...>Model.tt, а не <...>Model.Context.tt

0 голосов
/ 26 июня 2009

Я не верю, что ты можешь. Генератор объявляет все классы как частичные, что позволяет расширять его, но не позволяет помечать свойства пользовательскими атрибутами, поскольку он просто генерирует их. Единственное, что вы можете сделать, это написать свои собственные сущности.

...