Добавить атрибут в класс другой сборки
Можно ли как-то расширить тип, который определен в другой сборке, чтобы добавить атрибут к одному из его свойств?
Пример у меня в сборке FooBar:
public class Foo
{
public string Bar { get; set; }
}
Но в моей сборке пользовательского интерфейса я хочу передать этот тип стороннему инструменту, и для правильной работы этого стороннего инструмента мне нужно Bar
свойство иметь определенный атрибут. Этот атрибут определен в сторонней сборке, и я не хочу ссылки на эту сборку в моей сборке FooBar, так как FooBar содержит мой домен, это инструмент пользовательского интерфейса.
4 ответа
Вы не можете, если сторонний инструмент использует стандартное отражение, чтобы получить атрибуты для вашего типа.
Вы можете, если сторонний инструмент использует TypeDescriptor
API для получения атрибутов для вашего типа.
Пример кода для случая дескриптора типа:
public class Foo
{
public string Bar { get; set; }
}
class FooMetadata
{
[Display(Name = "Bar")]
public string Bar { get; set; }
}
static void Main(string[] args)
{
PropertyDescriptorCollection properties;
AssociatedMetadataTypeTypeDescriptionProvider typeDescriptionProvider;
properties = TypeDescriptor.GetProperties(typeof(Foo));
Console.WriteLine(properties[0].Attributes.Count); // Prints X
typeDescriptionProvider = new AssociatedMetadataTypeTypeDescriptionProvider(
typeof(Foo),
typeof(FooMetadata));
TypeDescriptor.AddProviderTransparent(typeDescriptionProvider, typeof(Foo));
properties = TypeDescriptor.GetProperties(typeof(Foo));
Console.WriteLine(properties[0].Attributes.Count); // Prints X+1
}
Если вы запустите этот код, вы увидите, что последняя консольная запись печатает плюс один атрибут, потому что Display
атрибут сейчас также рассматривается.
Нет. Добавить атрибуты к типам из отдельных сборок невозможно.
Однако вы можете создать свой собственный тип, который обернет сторонний тип. Поскольку у вас есть полный контроль над вашим классом-оберткой, вы можете добавить туда атрибуты.
Как насчет:
public class Foo
{
public virtual string Bar
}
public class MyFoo : Foo
{
[yourcustomattribute]
public overrides string Bar
}
Я думаю, что вам нужен какой-то уровень адаптера, который не позволит этой инфраструктурной зависимости просочиться в логику вашего домена. Возможно, вы сможете создать класс адаптера, который будет похож на объект передачи данных другой технологии. Этот класс находится в интеграционной сборке, которая зависит от сторонней библиотеки:
public class FooDTO {
[TheirAttribute]
public string Bar { get; set; }
}
Затем вы можете использовать что-то вроде AutoMapper, чтобы облегчить боль при смене представлений.
Тем не менее, идеальным решением является поддержка сторонними библиотеками дополнительных способов предоставления метаданных об их операциях. Может быть, вы можете попросить их об этой функции.