Можно ли добавить атрибут к свойству в частичном классе?

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

public partial class Hazaa
{
  public int Shazoo { get; set; }
}

Тогда я бы хотел, чтобы Shazoo был отнесен как SuperCool , но. Я хочу сделать это в другом файле. Поскольку я использую частичные классы, я могу добавить новые свойства следующим образом.

public partial class Hazaa
{
  [SuperCool]
  public int Wheee { get; set; }
}

Но могу ли я атрибут свойства, объявленного в первом примере, путем написания кода в последнем? Я сомневаюсь, что это возможно, но я буду рад скорректировать ситуацию. Если да, то какой синтаксис?

Ответ 1

Нет, вы не можете.

Вы можете прикреплять атрибуты только к тем членам, которые вы там заявляете, и если член также не объявлен как частичный (чтобы вы могли его переопределить в другом месте), вы не можете прикреплять атрибуты к членам, объявленным в другом частичном файле.

Ответ 2

Исходя из ваших требований, в качестве варианта вы можете использовать:

Примечание. Атрибуты, которые вы можете зарегистрировать таким образом, на самом деле не являются атрибутами вашего класса, но большинство сред, таких как ASP.NET MVC, используют их как собственные атрибуты класса.

Если вы хотите добавить атрибуты аннотаций данных, особенно в качестве проекта ASP.NET MVC, вы найдете этот способ полезным.

Также для других сред, таких как Windows Forms, которые не поддерживают MetadataTypeAttribute, вы можете просто добавить поддержку, используя AssociatedMetadataTypeTypeDescriptionProvider.

Решение не ограничивается атрибутами аннотаций данных, и вы можете использовать все виды атрибутов, которые имеют значение для ваших библиотек и сред.

Как определить дополнительные атрибуты?

Вы можете создать класс метаданных, который содержит свойства вашего исходного класса, декорированные подходящими атрибутами, а затем украсить частичный класс атрибутом MetadataType и представить класс метаданных для вашего исходного класса.

Как увидеть влияние этих атрибутов?

Фреймворки, такие как ASP.NET MVC, используют эти атрибуты так, как они определены в вашем исходном классе.

Также вы можете зарегистрировать AssociatedMetadataTypeTypeDescriptionProvider в качестве поставщика вашего исходного типа для других платформ или компонентов, которые могут захотеть использовать TypeDescriptor для получения информации о вашем типе.

Они действительно мои атрибуты класса?

Обратите внимание: таким образом, атрибуты действительно не принадлежат вашему исходному классу, но для большинства сред, таких как ASP.NET MVC или Windows Forms, которые используют TypeDescriptor для получения информации о типах, они действуют как исходные атрибуты вашего класса.

Поэтому, если вы хотите получить атрибуты для свойства с помощью отражения, вы не можете их видеть, но если вы используете механизм TypeDescriptor, вы можете их видеть.

Пример

Класс Хазаа:

public partial class Hazaa
{
    public int Shazoo { get; set; }
}

Класс HazaaMetadata

[MetadataType(typeof(HazaaMetadata))]
public partial class Hazaa
{
}

public class HazaaMetadata
{
    [DisplayName("Shazoo Name")]
    public int Shazoo { get; set; }
}

Использование ASP.NET MVC

вам не нужно ничего делать, чтобы заставить DisplayName работать, вы можете просто использовать Html.Labelfor или Html.DisplayNameFor, чтобы увидеть результат. В качестве текста метки будет отображаться "Имя Shazoo".

Использование Windows Forms

Где-то в вашем приложении (например, загрузка формы, main,...) зарегистрируйте провайдера следующим образом:

var provider = new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Hazaa));
TypeDescriptor.AddProvider(provider, typeof(Hazaa));

И в результате вы увидите, что PropertyGrid и DataGridView используют "Имя Shazoo" в качестве заголовка для свойства и заголовка столбца.

Ответ 3

конечно, вы можете сделать это, используя метаданные следующим образом:

public partial class Hazaa : EntityBase
{
    public int Shazoo { get; set; }
}

[MetadataTypeAttribute(typeof(HazaaMetadata))]
public partial class Hazaa : EntityBase
{
    internal sealed class HazaaMetadata
    {
        [SuperCool]
        public int Shazoo { get; set; }
    }
}