您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

C# 可以利用反射给只读属性赋值吗?

2025/11/18 3:40:47发布20次查看
结论:可以
验证demo如下:
using system; using system.collections.generic; using system.componentmodel; using system.data; using system.drawing; using system.linq; using system.text; using system.windows.forms; namespace icontest { public partial class form2 : form { public form2() { initializecomponent(); reflecttest rt = new reflecttest(); rt.gettype().getproperty("id").setvalue(rt, "guid", null); messagebox.show(rt.id); } } public class reflecttest { private string id; [readonly(true)] public string id { get { return id; } set { id = value; } } } }
运行winform程序输出:
小注:
typedescriptor.getproperties用来setvalue这没有作用:
typedescriptor.getproperties(rt)["id"].setvalue(rt, "guid");
那么为什么typedescriptor.getproperties用来setvalue没有效果呢?
将上面的代码拆成如下两句:
propertydescriptor prop = typedescriptor.getproperties(rt)["id"]; prop.setvalue(rt, "guid");
单点跟踪进去,可以发现:
在获取到propertydescriptor这个抽象类的实例后,在调用setvalue方法的时候,是从其子类reflectpropertydescriptor调用的。
而具体的实现是在子类:reflectpropertydescriptor中,从微软源码中找到reflectpropertydescriptor及setvalue
public override void setvalue(object component, object value) { #if debug if (propdescusageswitch.traceverbose) { string compname = "(null)"; string valname = "(null)"; if (component != null) compname = component.tostring(); if (value != null) valname = value.tostring(); debug.writeline("[" + name + "]: setvalue(" + compname + ", " + valname + ")"); } #endif if (component != null) { isite site = getsite(component); icomponentchangeservice changeservice = null; object oldvalue = null; object invokee = getinvocationtarget(componentclass, component); debug.assert(!isreadonly, "setvalue attempted on read-only property [" + name + "]"); if (!isreadonly) { // announce that we are about to change this component // if (site != null) { changeservice = (icomponentchangeservice)site.getservice(typeof(icomponentchangeservice)); debug.assert(!compmodswitches.commondesignerservices.enabled || changeservice != null, "icomponentchangeservice not found"); } // make sure that it is ok to send the onchange events // if (changeservice != null) { oldvalue = securityutils.methodinfoinvoke(getmethodvalue, invokee, (object[])null); try { changeservice.oncomponentchanging(component, this); } catch (checkoutexception coex) { if (coex == checkoutexception.canceled) { return; } throw coex; } } try { try { securityutils.methodinfoinvoke(setmethodvalue, invokee, new object[] { value }); onvaluechanged(invokee, eventargs.empty); } catch (exception t) { // give ourselves a chance to unwind properly before rethrowing the exception. // value = oldvalue; // if there was a problem setting the controls property then we get: // argumentexception (from properties set method) // ==> becomes inner exception of targetinvocationexception // ==> caught here if (t is targetinvocationexception && t.innerexception != null) { // propagate the original exception up throw t.innerexception; } else { throw t; } } } finally { // now notify the change service that the change was successful. // if (changeservice != null) { changeservice.oncomponentchanged(component, this, oldvalue, value); } } } } }
从代码中可以看出来,只读属性直接被跳过去了。。。。。。
那么propertyinfo有没有什么限制呢?
propertyinfo调用的setvalue如下所示:
在微软开源的代码中可以找到其具体实现如下:
[debuggerstepthroughattribute] [diagnostics.debuggerhidden] #if !feature_coreclr [targetedpatchingoptout("performance critical to inline across ngen image boundaries")] #endif public override void setvalue(object obj, object value, object[] index) { setvalue(obj, value, bindingflags.public | bindingflags.nonpublic | bindingflags.instance | bindingflags.static, null, index, null); } [debuggerstepthroughattribute] [diagnostics.debuggerhidden] public override void setvalue(object obj, object value, bindingflags invokeattr, binder binder, object[] index, cultureinfo culture) { methodinfo m = getsetmethod(true); if (m == null) throw new argumentexception(system.environment.getresourcestring("arg_setmethnotfnd")); object[] args = null; if (index != null) { args = new object[index.length + 1]; for(int i=0;i<index.length;i++) args[i] = index[i]; args[index.length] = value; } else { args = new object[1]; args[0] = value; } m.invoke(obj, invokeattr, binder, args, culture); }
暂时没有看到propertyinfo调用的setvalue有什么限制
propertyinfo.getsetmethod 方法 (boolean)
以上就是c# 可以利用反射给只读属性赋值吗?的内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product