创建具有可为 null 属性的 CustomAttributeBuilder

发布于 2024-10-21 00:49:17 字数 2103 浏览 0 评论 0原文

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

我尝试修改方法来检查属性是否属于可为空类型,但我还没有找到实际提供可为空值的方法,即下面的代码(这只是一个测试)不起作用因为 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]);
}

任何正确方向的解决方案或指针将不胜感激。

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 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

雨落□心尘 2024-10-28 00:49:17

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

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

这样你就可以节省大量代码。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文