Dot-Net

是否可以通過反射設置私有屬性?

  • October 14, 2009

我可以通過反射設置私有屬性嗎?

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);
}

引用自:https://stackoverflow.com/questions/1565734