1

我有以下代码作为使用反射生成接口的系统的一部分.emit

void IPropertyCreator.AddAttribute<T>(params object[] args)
{
    // Convert args to types
    var argTypes = new Type[args.Length];
    for (int i = 0; i < args.Length; ++i)
    {
        argTypes[i] = args[i] != null ? args[i].GetType() : null;
    }
    // Get constructor
    var ctorInfo = typeof(T).GetConstructor(argTypes);

    // Create custom attribute
    var attrBuilder = new CustomAttributeBuilder(ctorInfo, args);
    _propertyBuilder.SetCustomAttribute(attrBuilder);
}

在出现问题的情况下,我正在T使用带有单个 object参数的构造函数创建一个属性(类型参数),并且参数是一个decimal 属性具有(仅)以下构造函数

public DefaultValueAttribute(object value)

此代码适用于所有 POD 类型(bytecharint等),string但在使用decimal. 构造函数CustomAttributeBuilder失败,出现异常"Passed in argument value at index 0 does not match the parameter type"

调试显示所有变量都符合预期:
args有一个类型的元素object{decimal}
argTypes有一个元素类型=System.Decimal
ctorInfo正确选择了(唯一)采用对象参数的构造函数。

我已经证明可以通过直接传递十进制参数来实例化该属性:

decimal val = 123.456M;
var attr = new DefaultValueAttribute(val);

我尝试将小数转换为 anobject和 aSystem.Decimal无效。我怀疑这个问题与这样一个事实有关,decimal即不是 POD 类型而是结构。

我尝试向属性添加构造函数重载(采用decimal类型)。上述函数正确地选择了新的构造函数,但随后在同一个地方失败,除了“无效类型被用作自定义属性构造函数参数、字段或属性”之外

有谁知道我该如何解决这个问题?

4

1 回答 1

4

试着用普通的 C# 代码写这个:

class TestAttribute : Attribute {
    public TestAttribute(object value) { }
}

[Test(1.2m)]         // NOTE: CS0182
class Example { }

您根本不能将 System.Decimal 用于属性构造函数参数。双标没问题。C# 语言规范的第 17.1.3 节暗示了这个问题,但对这种特殊情况并不太具体。System.Decimal 有点像标准值类型的继子。例如,它从未在 Ecma 335 中提及。C# 编译器使它看起来像一个基本类型,但 CLR 不会以同样的方式对待它。

于 2013-08-24T14:14:47.550 回答