开发者

Creating a CustomAttributeBuilder with nullable property

While creating types and properties with TypeBuilder and PropertyBuilder I need to add custom attributes. However, the API I'm trying to create is abstracting as 开发者_JAVA技巧much reflection stuff as possible so in order to add attributes to types or properties the user supplies an actual attribute.

But as attributes can't be added to TypeBuilder or PropertyBuilder (as far as I've found) I need to create instances of CustomAttributeBuilder (which can be added) with matching values from the supplied attributes. I use the below method to do this and it works fine except for when an attribute has a nullable property.

If an attribute contains a nullable property an ArgumentException is thrown saying "An invalid type was used as a custom attribute constructor argument, field or property." when the last line of the method is executed.

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

I've tried to modify the method to check if a property is of a nullable type but I haven't found a way to actually supply a value that is nullable, ie the below code (which is just a test) doesn't work as nullableValue.GetType() will return 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]);
}

Any solutions or pointers in the right direction would be appreciated.


why dont you check the property, not the value.

Inside your GetWritableProperties where you are getting The PropertyInfo collection. You can at once get the properties and values like this:

creat a class to hold the PropertyInfo and Value

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

then change your method GetWritableProperties to:

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

With this you save alot of code.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜