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.
精彩评论