При создании типов и свойств с помощью TypeBuilder и PropertyBuilder мне нужно добавить пользовательские атрибуты. Однако API, который я пытаюсь создать, абстрагирует как можно больше отражений, поэтому для добавления атрибутов к типам или свойствам пользователь предоставляет фактический атрибут.
Но поскольку атрибуты не могут быть добавлены в TypeBuilder или PropertyBuilder (насколько мне известно), мне нужно создать экземпляры CustomAttributeBuilder (которые можно добавить) с соответствующими значениями из предоставленных атрибутов. Для этого я использую приведенный ниже метод, и он отлично работает, за исключением случаев, когда атрибут имеет свойство, допускающее значение NULL.
Если атрибут содержит свойство, допускающее значение NULL, создается исключение ArgumentException, говорящее: «Недопустимый тип использовался в качестве аргумента, поля или свойства конструктора настраиваемого атрибута». когда выполняется последняя строка метода.
private static CustomAttributeBuilder CreateAttributeWithValuesFromTemplate(
Attribute attribute)
{
var propertiesWithValues = new List<PropertyInfo>();
var nonNullPropertyValues = new List<Object>();
if (attribute != null)
{
var properties = GetWritableProperties(attribute);
object[] propertyValues = GetPropertyValues(attribute, properties);
for (int i = 0; i < properties.Length; i++)
{
if (propertyValues[i] == null)
continue;
propertiesWithValues.Add(properties[i]);
nonNullPropertyValues.Add(propertyValues[i]);
}
}
ConstructorInfo constructor;
if (attributeSpecification.Constructor != null)
constructor = attributeSpecification.Constructor;
else
constructor = attributeSpecification.Type.GetConstructor(new Type[] { });
object[] constructorParams;
if (attributeSpecification.Constructor != null)
constructorParams = attributeSpecification.ConstructorParameters;
else
constructorParams = new object[] {};
return new CustomAttributeBuilder(constructor, constructorParams,
propertiesWithValues.ToArray(), nonNullPropertyValues.ToArray());
}
Я попытался изменить метод, чтобы проверить, имеет ли свойство тип, допускающий значение NULL, но я не нашел способа фактически указать значение, допускающее значение NULL, т.е. приведенный ниже код (который является просто тестом) не работает поскольку nullableValue.GetType() вернет Int32.
if(properties[i].PropertyType.IsGenericType
&& properties[i].PropertyType.GetGenericTypeDefinition()== typeof(Nullable<>)) {
Nullable<int> nullableValue = new Nullable<int>();
nonNullPropertyValues.Add(nullableValue);
} else {
nonNullPropertyValues.Add(propertyValues[i]);
}
Любые решения или указатели в правильном направлении будут оценены.
1 ответ
Почему бы вам не проверить свойство, а не значение.
Внутри вашего GetWritableProperties, где вы получаете коллекцию PropertyInfo. Вы можете сразу получить такие свойства и значения:
Создайте класс для хранения PropertyInfo и Value
public class InfoAndValue
{
public PropertyInfo Info { get; set; }
public Object Value { get; set; }
}
Затем измените свой метод GetWritableProperties на:
static IEnumerable<InfoAndValue> GetWritableProperties(Attribute attribute)
{
var collection = from p in attribute.GetType().GetProperties()
where !p.PropertyType.Name.StartsWidth("Nullable`1")
select new InfoAndValue {
Info = p,
Value = p.GetValue(attribute, null)
};
return collection.Where(x => x.Value != null);
}
При этом вы экономите много кода.
Похожие вопросы
Новые вопросы
c#
C # (произносится как «резкий») - это высокоуровневый, статически типизированный язык программирования с несколькими парадигмами, разработанный Microsoft. Код C # обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, включая, среди прочего, .NET Framework, .NET Core и Xamarin. Используйте этот тег для вопросов о коде, написанном на C # или в формальной спецификации C #.