Чи можу я визначити властивості в часткових класах, а потім позначити їх атрибутами в іншому частковому класі?


84

Чи є спосіб, як я можу створити згенерований файл коду так:

public partial class A {
public string a {get; set;}
}

а потім в іншому файлі:

public partial class A {
[Attribute("etc")]
public string a {get; set;}
}

Так що я можу створити клас, згенерований з бази даних, а потім використовувати негенерований файл для його розмітки?


Скільки "генерується з бази даних"? Тільки визначення властивостей або код також?
snemarch

1
Коротка відповідь, ні. Довга відповідь, копія stackoverflow.com/questions/456624/… .
Kirk Woll,

@snemarch: лише визначення властивостей, я планую робити будь-який інший код вручну.
Chris McCall,

1
Чи можете ви зробити з інтерфейсом + спліт реалізації замість часткового класу? Створіть інтерфейс з бази даних, впровадьте (і додайте атрибути) у реалізацію.
snemarch

так, це можливо, але з використанням метаданих тоді інший частковий успадковуйте ці метадані
CyberNinja

Відповіді:


33

Щось подібне я бачив у статті Скотта Гатрі (ближче до кінця), хоча сам не пробував.
http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx

[MetadataType(typeof(Person_Validation))]
public partial class Person
{
    // Partial class compiled with code produced by VS designer
}

[Bind(Exclude="ID")]
public class Person_Validation
{
    [Required(ErrorMessage = "First Name Required")]
    [StringLength(50, ErrorMessage = "Must be under 50 characters")]
    public string FirstName { get; set; }

    [Required(ErrorMessage = "Last Name Required")]
    [StringLength(50, ErrorMessage = "Must be under 50 characters")]
    public string LastName { get; set; }

    [Required(ErrorMessage = "Age Required")]
    [Range(0, 120, ErrorMessage = "Age must be between 0 and 120")]
    public int Age { get; set; }

    [Required(ErrorMessage = "Email Required")]
    [Email(ErrorMessage = "Not a valid email")]
    public string Email { get; set; }
}

10
Ця відповідь має згадку, але вона не є загальним рішенням питання, поставленого ОП. Споживачі атрибутів все одно повинні знати, щоб шукати клас метаданих - тобто ці атрибути не повертаються Attribute.GetCustomAttribute (...). (На щастя для багатьох випадків використання, споживачі написані MS, і в певних ситуаціях це спрацює.)
Kirk Woll

1
Це рішення НЕ вирішує проблему. Чому ми прагнемо прикрасити учасників в іншому файлі? Тому що клас ЗАПИСАНО кожного разу, коли дизайнер запускає. Таким чином, ваш атрибут [MetaDataType ...буде очищений щоразу, коли дизайнер запускається

2
@Desolator - Ідея полягає в тому, що ви не поміщаєте MetadataTypeатрибут у файл, згенерований дизайнером, ви поміщаєте його в інший файл, де визначено частковий клас Person.
Ден Думітру

1
проблема з цим рішенням полягає в тому, що клас повинен був бути частковим
CyberNinja

85

Ось рішення, яке я використовував для таких випадків. Це корисно, якщо у вас є автоматично згенеровані класи, які ви хочете прикрасити атрибутами. Скажімо, це автоматично згенерований клас:

public partial class UserProfile
{
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
}

І скажімо, я хотів би додати атрибут, щоб вказати, що UserId є ключем. Потім я створив би частковий клас в іншому файлі, подібному до цього:

[Table("UserProfile")]
[MetadataType(typeof(UserProfileMetadata))]
public partial class UserProfile
{
    internal sealed class UserProfileMetadata
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int UserId { get; set; }
    }
}

Чудове рішення. Я знав, що ви можете прикрасити частковий клас атрибутами у декількох файлах і навіть додати інтерфейси та успадкований клас до його оголошення, але я не встановив з'єднання з MetadataTypeатрибутом. Молодці!
Пфлугс

Що робити, якщо я хочу додати атрибут до конструктора UserProfile?
Ботіс

2
MetadataTypeне існує в .NET Core
WoII

2
.net core ModelMetadataType
koristi

1
Підтримка @Dave повинна надійти в .NET Core 3.0
Роджер Вілкокс,

2

Це моя відповідь у
файлах різних класів, або ви можете комбінувати метадані в одному файлі, але зберігати простір імен однаковим ... так що вони можуть бачити одне одного очевидно.

майте на увазі, коли ви оновлюєте свою модель, наприклад, додаєте більше стовпців, вам також доведеться оновити клас проекту.

--your model class
public partial class A {
    public string a {get; set;}
}

--your project class 
public class Ametadata {
     [Attribute("etc")]
     public string a {get; set;}
}


[MetadataType(typeof(Ametadata))]
public partial class A
{
}

1

Вам потрібно визначити частковий клас для вашого Aкласу, як показано нижче

using System.ComponentModel.DataAnnotations;

// your auto-generated partial class
public partial class A 
{
    public string MyProp { get; set; }
}

[MetadataType(typeof(AMetaData))]
public partial class A 
{

}

public class AMetaData
{
    [System.ComponentModel.DefaultValue(0)]
    public string MyProp { get; set; }
}

0

Не як такі; компілятор скаржиться, що член визначений у декількох частинах. Однак, оскільки використання спеціальних атрибутів відображає характер, ви можете визначити клас "метаданих" і використовувати його для розміщення декораторів.

public class A
{
   public string MyString;
}

public class AMeta
{
   [TheAttribute("etc")]
   public object MyString;
}

...

var myA = new A();
var metaType = Type.GetType(myA.GetType().Name + "Meta");
var attributesOfMyString = metaType.GetMember("MyString").GetCustomAttributes();

1
Як часто буває так, що актор, який додає атрибути до своїх властивостей, є також людиною, яка їх споживає, і тому знатиме, що потрібно шукати магічні класи "Мета"?
Kirk Woll,

Досить часто, з мого досвіду. Це не підійде для існуючого аспектно-орієнтованого фреймворку, але якщо ви прикрашали свій домен, скажімо, спеціальними атрибутами перевірки, ви шукаєте їх і можете визначити, де. Моя команда зробила саме це в одному з наших проектів. Головний недолік - не шукати іншого класу; це підтримка двох паралельних класів при розробці, один функціональний, інший декоративний. Це було б проблемою і в часткових класах, якби ви спочатку змогли визначити часткові поля / властивості.
KeithS
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.