使用nullable属性创建CustomAttributeBuilder

时间:2011-03-06 00:27:28

标签: c# reflection

使用TypeBuilder和PropertyBuilder创建类型和属性时,我需要添加自定义属性。但是,我试图创建的API尽可能多地抽象反射内容,因此为了向类型或属性添加属性,用户提供实际属性。

但由于属性无法添加到TypeBuilder或PropertyBuilder(据我所知),我需要创建CustomAttributeBuilder(可以添加)的实例,并使用提供的属性中的匹配值。我使用下面的方法来执行此操作,除了属性具有可空属性时,它才能正常工作。

如果属性包含可空属性,则抛出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 :(得分:0)

为什么不检查财产,而不是价值。

在您获取PropertyInfo集合的GetWritableProperties中。 您可以立即获取如下属性和值:

创建一个类来保存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);
}

这样就可以节省很多代码。