【问题标题】:Setting default value of the property with PropertyBuilder and SetConstant使用 PropertyBuilder 和 SetConstant 设置属性的默认值
【发布时间】:2012-08-13 00:48:10
【问题描述】:

我有一段非常简单的代码

var propertyBuilder =
    typeBuilder.DefineProperty(upperName, PropertyAttributes.None, propertyType, new[] { propertyType });
propertyBuilder.SetConstant(Convert.ChangeType(propertyInfo.Default, propertyType));

之后,当我调用CreateType() 方法并创建类的实例时,我试图检查分配了默认值的属性的值,但我看不到任何更改。

创建类的实例后,我无法使用SetValue 方法,因为所有构造的类型都存储在元数据字典中,并且可以从代码中的不同位置使用。

有什么建议为什么SetConstant 方法不起作用?

【问题讨论】:

  • 我不明白你为什么不能使用SetValue()SetValue() 仅影响该类型的一个实例,它不会影响“代码中的不同位置”(除非它们共享该类型的相同实例)。
  • 另外,您真的要创建索引器(即带参数的属性)而不是普通属性吗?因为这就是设置 parameterTypes 所做的。
  • 我需要影响该类型的所有实例,这就是为什么我想在构建类型时使用 SetConstant 方法
  • 我把最后一个参数改成了null,但还是一样

标签: c# .net reflection properties reflection.emit


【解决方案1】:

SetConstant() 不会做你认为的那样。它设置了与属性关联的“默认值”,但该值实际上并未在任何地方使用(尽管您可以使用GetConstantValue() 检索它)。

要从属性的 getter 中实际返回一些常量值,您需要创建 getter 方法并将其 IL 设置为返回值。但是由于您不能在程序集本身中存储任意类型,因此通常很难做到这一点。例如,如果属性是int,它看起来像这样:

var getMethodBuilder = typeBuilder.DefineMethod(
    "get_" + upperName, MethodAttributes.Public, typeof(int), Type.EmptyTypes);

var il = getMethodBuilder.GetILGenerator();
il.Emit(OpCodes.Ldc_I4, defaultValue);
il.Emit(OpCodes.Ret);

var propertyBuilder = typeBuilder.DefineProperty(
    upperName, PropertyAttributes.None, typeof(int), Type.EmptyTypes);
propertyBuilder.SetGetMethod(getMethodBuilder);

ldc.i4 是一条 IL 指令,用于将常量整数加载到 IL 堆栈中。对于其他类型,您需要不同的说明。

【讨论】:

  • 酷,但在这种情况下,SetConstant 方法最常见的用法是什么?
  • 另外,我只需要在创建实例时第一次返回默认值。之后用户可以修改属性的值
  • 我从未见过SetConstant() 的任何用法,我不知道它是用来做什么的。如果你想要更复杂的行为,你将需要更复杂的 IL。在您的情况下,您可能希望创建一个支持字段并将其设置为默认值。
猜你喜欢
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-07
  • 2012-04-07
  • 1970-01-01
相关资源
最近更新 更多