我可以使用反射调用结构 属性 的 "Set" 方法吗?
Can I call the "Set" method of a struct property using reflection?
我定义了一个结构体:
public struct Settable
{
public string SettableProperty { get; set; }
}
我可以用通常的方式设置结构的 属性 的值:
s.SettableProperty = "Abc";
但是,当我创建一个方法来尝试通过反射设置 属性 时:
public T CreateWithValue<T>(string propName, string propValue)
{
var retObj = Activator.CreateInstance<T>();
var prop = typeof(T).GetProperty(propName);
var _ = prop.SetMethod.Invoke(retObj, new object[] { propValue});
return retObj;
}
...这样称呼它:
var x = CreateWithValue<Settable>("SettableProperty", "Abc");
...我最终将 SettableProperty
初始化为其默认值 null
。 (没有抛出异常。)
请注意,如果我将 Settable 定义为 class 而不是 struct,则值会按预期设置。
是否可以使用反射设置结构属性?
这里的问题是retObj
是T
,一个值类型,但是Invoke
需要object
。这个 boxes 值,它在堆上(在盒子内)创建一个独立的副本,然后您对其进行变异。 retObj
中的本地副本在这里不会受到任何影响,因为它是该值的完全断开连接的副本。
改为考虑:
public T CreateWithValue<T>(string propName, string propValue)
{
object retObj = Activator.CreateInstance<T>();
var prop = typeof(T).GetProperty(propName);
prop.SetMethod.Invoke(retObj, new object[] { typedValue });
return (T)retObj;
}
这会创建 earlier 框,然后将其拆箱以获得修改后的值。但是,它不是很有效(注意:我没有 添加 任何低效率;使用具有值的 object
API 时,低效率是固有的-类型)。如果您愿意变得更脏,可以删除分配。
我定义了一个结构体:
public struct Settable
{
public string SettableProperty { get; set; }
}
我可以用通常的方式设置结构的 属性 的值:
s.SettableProperty = "Abc";
但是,当我创建一个方法来尝试通过反射设置 属性 时:
public T CreateWithValue<T>(string propName, string propValue)
{
var retObj = Activator.CreateInstance<T>();
var prop = typeof(T).GetProperty(propName);
var _ = prop.SetMethod.Invoke(retObj, new object[] { propValue});
return retObj;
}
...这样称呼它:
var x = CreateWithValue<Settable>("SettableProperty", "Abc");
...我最终将 SettableProperty
初始化为其默认值 null
。 (没有抛出异常。)
请注意,如果我将 Settable 定义为 class 而不是 struct,则值会按预期设置。
是否可以使用反射设置结构属性?
这里的问题是retObj
是T
,一个值类型,但是Invoke
需要object
。这个 boxes 值,它在堆上(在盒子内)创建一个独立的副本,然后您对其进行变异。 retObj
中的本地副本在这里不会受到任何影响,因为它是该值的完全断开连接的副本。
改为考虑:
public T CreateWithValue<T>(string propName, string propValue)
{
object retObj = Activator.CreateInstance<T>();
var prop = typeof(T).GetProperty(propName);
prop.SetMethod.Invoke(retObj, new object[] { typedValue });
return (T)retObj;
}
这会创建 earlier 框,然后将其拆箱以获得修改后的值。但是,它不是很有效(注意:我没有 添加 任何低效率;使用具有值的 object
API 时,低效率是固有的-类型)。如果您愿意变得更脏,可以删除分配。