16

正如.NET 反射设置私有属性中所厌恶的那样,可以使用私有设置器设置属性。但是当在基类中定义属性时,会抛出 System.ArgumentException:“找不到属性集方法”。

一个例子可以是:

using System;
class Test
{
    public DateTime ModifiedOn { get; private set;}
}

class Derived : Test
{
}

static class Program
{
    static void Main()
    {
        Derived p = new Derived ();
        typeof(Derived).GetProperty("ModifiedOn").SetValue(
            p, DateTime.Today, null);
        Console.WriteLine(p.ModifiedOn);
    }
}

有谁知道解决这种情况的方法?

编辑:给出的示例是对问题的简单说明。在现实世界的场景中,我不知道属性是定义在基类中,还是定义在基类的基类中。

4

4 回答 4

20

我有一个类似的问题,我的私有财产在基类中声明。我使用DeclaringType来获取定义属性的类的句柄。

using System;
class Test
{
    public DateTime ModifiedOn { get; private set;}
}

class Derived : Test
{
}

static class Program
{
    static void Main()
    {
        Derived p = new Derived ();

        PropertyInfo property = p.GetType().GetProperty("ModifiedOn");
        PropertyInfo goodProperty = property.DeclaringType.GetProperty("ModifiedOn");

        goodProperty.SetValue(p, DateTime.Today, null);

        Console.WriteLine(p.ModifiedOn);
    }
}
于 2013-09-19T15:06:45.607 回答
10

我认为这会起作用:

using System;
class Test
{
    public DateTime ModifiedOn { get; private set;}
}

class Derived : Test
{
}

static class Program
{
    static void Main()
    {
        Derived p = new Derived ();
        typeof(Test).GetProperty("ModifiedOn").SetValue(
            p, DateTime.Today, null);
        Console.WriteLine(p.ModifiedOn);
    }
}

您需要从其实际定义的类而不是派生类中获取属性定义

编辑:

要在任何基类上选择它,您需要在所有父类上查找它。

像这样的东西然后递归到基类,直到你点击对象或找到你的财产

typeof(Derived ).GetProperties().Contains(p=>p.Name == "whatever")
于 2012-04-06T09:18:24.380 回答
8

@LukeMcGregor 的另一种选择是使用 BaseType

typeof(Derived)
    .BaseType.GetProperty("ModifiedOn")
    .SetValue(p, DateTime.Today, null);
于 2012-04-06T09:21:51.547 回答
5

我做了这个可重用的方法。它处理我的场景。

    private static void SetPropertyValue(object parent, string propertyName, object value)
    {
        var inherType = parent.GetType();
        while (inherType != null)
        {
            PropertyInfo propToSet = inherType.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
            if (propToSet != null && propToSet.CanWrite)
            {
                propToSet.SetValue(parent, value, null);
                break;
            }

            inherType = inherType.BaseType;
        }
    }
于 2013-08-01T05:22:28.073 回答