【问题标题】:.NET Reflection set private property.NET 反射集私有属性
【发布时间】:2009-11-22 10:51:04
【问题描述】:

如果你有这样定义的属性:

private DateTime modifiedOn;
public DateTime ModifiedOn
{
    get { return modifiedOn; }
}

如何使用 Reflection 将其设置为某个值?

我都试过了:

dto.GetType().GetProperty("ModifiedOn").SetValue(dto, modifiedOn, null);

和

dto.GetType().GetProperty("modifiedOn").SetValue(dto, modifiedOn, null);

但没有任何成功。抱歉,如果这是一个愚蠢的问题,但这是我第一次将反射与 C#.NET 一起使用。

【问题讨论】:

    标签: c# .net reflection


    【解决方案1】:

    那个没有没有二传手;你需要:

    public DateTime ModifiedOn
    {
        get { return modifiedOn; }
        private set {modifiedOn = value;}
    }
    

    (您可能必须使用BindingFlags - 我稍后会尝试)

    如果没有 setter,您将不得不依赖模式/字段名称(这很脆弱),或者解析 IL(非常困难)。

    以下工作正常:

    using System;
    class Test {
        private DateTime modifiedOn;
        public DateTime ModifiedOn {     
            get { return modifiedOn; }
            private set { modifiedOn = value; }
        }
    }
    static class Program {
        static void Main() {
            Test p = new Test();
            typeof(Test).GetProperty("ModifiedOn").SetValue(
                p, DateTime.Today, null);
            Console.WriteLine(p.ModifiedOn);
        }
    }
    

    它也适用于自动实现的属性:

    public DateTime ModifiedOn { get; private set; }
    

    (依赖字段名称会严重中断)

    【讨论】:

    • 酷,没想到能在二传手面前拥有私密性。而且我必须检查我猜的那些 BindingFlags。谢谢。
    • 如果整个属性都是私有的,您似乎只需要BindingFlags。
    • 仍然不起作用,所以我想我必须使用那些 BindingFlags?
    • 定义“不起作用”——会发生什么?我发布的示例效果很好......还有:你在使用 CF 吗?银光?还是常规的.NET? (这很重要......)
    • 一瞬间,可能忘记了什么。
    【解决方案2】:

    您可以尝试设置支持字段而不是属性;你应该使用GetField() 而不是GetProperty()。

    【讨论】:

    • 虽然这样可行,但访问字段通常是一种更加脆弱的反射形式。例如,当有人发现 C# 3.0 并制作它时会发生什么:public DateTime ModifiedOn { get; private set; }?
    • 如果您确实想设置支持字段,以尽量减少破坏的机会,我会尝试找到以下三种可能性中的每一种:(1)同名,忽略案子。 (2) 下划线+同名,不区分大小写。 (3) 自动属性支持字段的默认命名方案(在 SO 上很容易找到)。
    • 请注意,GetField() 有一个允许 IgnoreCase 的重载。
    【解决方案3】:

    如果您的属性没有设置器,则不能对其调用 SetValue。

    【讨论】:

      【解决方案4】:

      您需要设置字段,因为您没有设置属性来设置属性。 非公共对象需要额外的 BindingFlags.NonPublic。

      dto.GetType().
          GetField("modifiedOn", 
          BindingFlags.NonPublic|BindingFlags.SetField|BindingFlags.Instance).
          SetValue(dto, valueToSet);
      

      【讨论】:

        【解决方案5】:

        如果你有一个带有 setter 的私有属性,那么你可以使用这个扩展方法来设置一个值:

        using System.Reflection;
        
        public static class ObjectExtensions
        {
            public static void SetPrivateValue<T>(this T obj, string propertyName, object value)
            {
                var type = typeof(T);
                type.GetTypeInfo().GetDeclaredProperty(propertyName).SetValue(obj, value, null);
            }
        }
        

        【讨论】:

          【解决方案6】:

          考虑到set 可能存在也可能不存在,一种方法是使用特定的访问器,这可能是最正确的方法

          var myc = new MyClass();
          var pi = typeof(MyClass).GetProperty("Prop1", BindingFlags.NonPublic | BindingFlags.Instance);
          
          if (pi.SetMethod != null) // check if you have 'set' accessor
              pi.SetMethod.Invoke(myc, new object[]{ someValue });
          else
          {
              // do nothing OR
              throw new Exception("Attempted to set read-only property " + pi.Name);
          }
          

          【讨论】:

            猜你喜欢
            • 2012-01-23
            • 1970-01-01
            • 2011-01-22
            • 1970-01-01
            • 2012-02-10
            • 2014-02-14
            • 1970-01-01
            • 1970-01-01
            • 2010-12-06
            相关资源
            最近更新 更多