Создание CustomAttributeBuilder с нулевым свойством - PullRequest
1 голос
/ 06 марта 2011

При создании типов и свойств с TypeBuilder и PropertyBuilder мне нужно добавить пользовательские атрибуты. Тем не менее, API, который я пытаюсь создать, абстрагирует как можно больше отражений, чтобы добавить атрибуты к типам или свойствам, которые пользователь предоставляет фактическим атрибутом.

Но поскольку атрибуты не могут быть добавлены в TypeBuilder или PropertyBuilder (насколько я обнаружил), мне нужно создать экземпляры CustomAttributeBuilder (которые можно добавить) с соответствующими значениями из предоставленных атрибутов. Для этого я использую приведенный ниже метод, и он работает нормально, за исключением случаев, когда атрибут имеет свойство, допускающее значение 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());
}

Я пытался изменить метод, чтобы проверить, имеет ли свойство обнуляемый тип, но я не нашел способа на самом деле предоставить значение, которое можно обнулять, то есть приведенный ниже код (который является просто тестом) не не работает как 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 Ответ

0 голосов
/ 10 марта 2011

почему вы не проверяете свойство, а не значение.

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

создать класс для хранения PropertyInfo и Value

<code>public class InfoAndValue
{
    public PropertyInfo Info { get; set; }
    public Object Value { get; set; }
}

затем измените ваш метод GetWritableProperties на:

<code>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);
}

С этим вы экономите много кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...