Я хочу установить атрибут в общедоступном свойстве в .NET, однако у меня нет доступа к самому явному свойству, так как это был код, созданный в другом файле.
У меня есть это поле:
public virtual string Name { get; set; }
Я хочу установить это:
[ValidateNonEmpty("Name is required", ExecutionOrder = 1)]
public virtual string Name { get; set; }
Мой класс отмечен как частичный, но у вас не может быть частичных свойств. Я думал, что наткнулся на что-то с классом MetadataType, который является новой функцией динамических данных и DataAnnotations, но, увы, я чувствую, что его можно использовать только с динамическими данными, правда ли это?
Цитаты: http://blogs.oosterkamp.nl/blogs/jowen/archive/2008/10/16/metadatatype-attribute.aspxhttp://blogs.msdn.com/davidebb/archive/2008/06/16/dynamic-data-and-the-associated-metadata-class.aspx
Есть ли способ установить эти атрибуты (даже через web.config!), Не касаясь сгенерированного кода класса?
Заранее спасибо, Грэм





Это известная неприятность; вы просто не можете добавлять метаданные к созданным членам.
Здесь есть 6 вариантов (в порядке увеличения усилий):
[ValidateNonEmpty("Name", "Name is required", ExecutionOrder = 1)] - затем добавьте несколько атрибутов в определение частичного классаTypeDescriptionProvider для предоставления динамических метаданных (много-много работы) - при условии, что потребитель уважает TypeDescriptor; большинство потребителей, связанных с привязкой, делают, но, например, Expression (используемый многими поставщиками LINQ) неОбычно у меня получается первый вариант, если он не является системным атрибутом ([DisplayName] и т. д.). Если [ValidateNonEmpty] определяется динамическими данными, возможно, вы не сможете этого сделать.
Я понимаю, что это не то же самое, что запрос истинных атрибутов, но для того, что мне нужно, похоже, что в этом случае он будет служить цели. Что здорово.
Надеюсь, это имеет смысл. Теперь я могу видеть, был ли объявлен атрибут проверки, и работать соответствующим образом. Теперь я просто надеюсь, что у меня не будет накладных расходов, если я использую класс атрибутов MetadataType вместо того, чтобы создавать свой собственный, который просто сообщает ему, в каком классе смотреть свойства.
Другой вариант - обернуть свойства внутри несгенерированных свойств одного и того же класса. Не идеально, потому что у вас могут быть двойные свойства, но если вы можете заставить свой генератор создавать защищенные свойства, это будет довольно хороший подход.
Просто пришлось столкнуться с этой проблемой: Entity Framework генерирует классы, я хочу сериализовать их в JSON с более простыми именами.
// GENERATED BY EF
public partial class ti_Users
{
public ti_Users()
{
this.ti_CardData = new HashSet<ti_CardData>();
this.ti_Orders = new HashSet<ti_Orders>();
}
protected int userId { get; set; }
protected string userName { get; set; }
protected string userEmail { get; set; }
protected string userPassHash { get; set; }
protected Nullable<System.DateTime> userLastLogin { get; set; }
protected string userLastIP { get; set; }
public virtual ICollection<ti_CardData> ti_CardData { get; set; }
public virtual ICollection<ti_Orders> ti_Orders { get; set; }
}
и дополнительный класс:
[JsonObject(memberSerialization: MemberSerialization.OptIn)]
public partial class ti_Users
{
[JsonProperty]
public int UserId
{
get { return this.userId; }
set { this.userId = value; }
}
[JsonProperty]
public string Name
{
get { return this.userName; }
set { this.userName = value; }
}
[JsonProperty]
public string Email
{
get { return this.userEmail; }
set { this.userEmail = value; }
}
[JsonProperty]
public string PassHash
{
get { return this.userPassHash; }
set { this.userPassHash = value; }
}
}
Поскольку сгенерированный класс является частичным классом, должно работать следующее:
Например:
// Decorate the properties with attributes as required
public interface IMyInterface
{
[ValidateNonEmpty("Name is required")]
string Name { get; set; }
}
// This is the partial class I created, that implements the interface
public partial class MyGeneratedClass : IMyInterface
{
}
// This is the auto-generated class
public partial class MyGeneratedClass
{
public virtual string Name { get; set; }
}
Я получил эту идею от компьютерщики.
Я думаю, тогда вам нужно будет добавить каждое свойство из вашего базового класса в интерфейс - утомительное упражнение, если у вас много сгенерированных классов и много свойств.
Это отличное решение, но оно не сработало для моей проблемы. Я использую EF 6 с классами, созданными первым кодом из существующей базы данных. Один из столбцов в таблице - это ИДЕНТИФИКАЦИЯ с автоматически сгенерированными значениями. Однако сгенерированный частичный класс не предоставил атрибут [DatabaseGenerated (DatabaseGeneratedOption.Identity)], необходимый для генерации ключа базой данных. Результат - ошибка «Невозможно вставить явное значение для столбца идентификаторов в таблицу mytable, если для IDENTITY_INSERT установлено значение OFF.». Я попробовал ваше решение, но оно не сработало. Но если я добавлю атрибут к исходному сгенерированному классу, он действительно сработает. Поэтому я все еще пытаюсь найти решение, которое не требует изменения автоматически сгенерированного файла.
Вот код, который я пытался использовать с вашим решением:
public interface IMyTable
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
int ID { get; set; }
}
public partial class MyTable : IMyTable
{
}
исходный сгенерированный код:
[Table("MyTable")]
public partial class MyTable
{
[Key]
[Column(Order = 1)]
public int ID { get; set; }
}
Спасибо, Марк, я подумал, что это может быть так. Мне удалось перебрать свойства моего объявленного класса «MetadataType» в тот момент, когда я хотел узнать об атрибутах, и я просто сравниваю имя «мета-свойства» с реальным свойством.