Dot-Net
是否可以通過反射設置私有屬性?
我可以通過反射設置私有屬性嗎?
public abstract class Entity { private int _id; private DateTime? _createdOn; public virtual T Id { get { return _id; } private set { ChangePropertyAndNotify(ref _id, value, x => Id); } } public virtual DateTime? CreatedOn { get { return _createdOn; } private set { ChangePropertyAndNotify(ref _createdOn, value, x => CreatedOn); } } }我嘗試了以下方法,但它不起作用,其中
t表示一種類型Entity:var t = typeof(Entity); var mi = t.GetMethod("set_CreatedOn", BindingFlags.Instance | BindingFlags.NonPublic);我想我可以做到這一點,但我無法解決。
t.GetProperty("CreatedOn") .SetValue(obj, new DateTime(2009, 10, 14), null);編輯:由於該屬性本身是公開的,因此您顯然不需要使用
BindingFlags.NonPublic它來查找它。儘管 setter 的可訪問性較低,但呼叫SetValue仍然可以滿足您的期望。
是的:
/// <summary> /// Returns a _private_ Property Value from a given Object. Uses Reflection. /// Throws a ArgumentOutOfRangeException if the Property is not found. /// </summary> /// <typeparam name="T">Type of the Property</typeparam> /// <param name="obj">Object from where the Property Value is returned</param> /// <param name="propName">Propertyname as string.</param> /// <returns>PropertyValue</returns> public static T GetPrivatePropertyValue<T>(this object obj, string propName) { if (obj == null) throw new ArgumentNullException("obj"); PropertyInfo pi = obj.GetType().GetProperty(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (pi == null) throw new ArgumentOutOfRangeException("propName", string.Format("Property {0} was not found in Type {1}", propName, obj.GetType().FullName)); return (T)pi.GetValue(obj, null); } /// <summary> /// Returns a private Property Value from a given Object. Uses Reflection. /// Throws a ArgumentOutOfRangeException if the Property is not found. /// </summary> /// <typeparam name="T">Type of the Property</typeparam> /// <param name="obj">Object from where the Property Value is returned</param> /// <param name="propName">Propertyname as string.</param> /// <returns>PropertyValue</returns> public static T GetPrivateFieldValue<T>(this object obj, string propName) { if (obj == null) throw new ArgumentNullException("obj"); Type t = obj.GetType(); FieldInfo fi = null; while (fi == null && t != null) { fi = t.GetField(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); t = t.BaseType; } if (fi == null) throw new ArgumentOutOfRangeException("propName", string.Format("Field {0} was not found in Type {1}", propName, obj.GetType().FullName)); return (T)fi.GetValue(obj); } /// <summary> /// Sets a _private_ Property Value from a given Object. Uses Reflection. /// Throws a ArgumentOutOfRangeException if the Property is not found. /// </summary> /// <typeparam name="T">Type of the Property</typeparam> /// <param name="obj">Object from where the Property Value is set</param> /// <param name="propName">Propertyname as string.</param> /// <param name="val">Value to set.</param> /// <returns>PropertyValue</returns> public static void SetPrivatePropertyValue<T>(this object obj, string propName, T val) { Type t = obj.GetType(); if (t.GetProperty(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) == null) throw new ArgumentOutOfRangeException("propName", string.Format("Property {0} was not found in Type {1}", propName, obj.GetType().FullName)); t.InvokeMember(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty | BindingFlags.Instance, null, obj, new object[] { val }); } /// <summary> /// Set a private Property Value on a given Object. Uses Reflection. /// </summary> /// <typeparam name="T">Type of the Property</typeparam> /// <param name="obj">Object from where the Property Value is returned</param> /// <param name="propName">Propertyname as string.</param> /// <param name="val">the value to set</param> /// <exception cref="ArgumentOutOfRangeException">if the Property is not found</exception> public static void SetPrivateFieldValue<T>(this object obj, string propName, T val) { if (obj == null) throw new ArgumentNullException("obj"); Type t = obj.GetType(); FieldInfo fi = null; while (fi == null && t != null) { fi = t.GetField(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); t = t.BaseType; } if (fi == null) throw new ArgumentOutOfRangeException("propName", string.Format("Field {0} was not found in Type {1}", propName, obj.GetType().FullName)); fi.SetValue(obj, val); }