【问题标题】:"Property set method not found" error during reflection反射期间出现“找不到属性集方法”错误
【发布时间】:2012-02-20 15:55:02
【问题描述】:

我正在尝试反映一些类属性并以编程方式设置它们,但我的某个 PropertyInfo 过滤器似乎无法正常工作:

//Get all public or private non-static properties declared in this class (no inherited properties) - that have a getter and setter.
PropertyInfo[] props = this.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.SetProperty );

我在线路上遇到错误

pi.SetValue(this, valueFromData, null);

因为属性只有get{}方法,没有set{}方法。

我的问题是,为什么这个属性没有从 props 中过滤掉?我认为这就是 BindingFlags.SetProperty 的目的。

没有被过滤掉的属性是:

    public String CollTypeDescription
    {
        get { return _CollTypeDescription; }
    }

请注意,我想过滤无法提前使用的属性,因为我会一次性将它们全部列出。我不想使用pi.GetSetMethod(),事后确定我是否可以使用setter。

【问题讨论】:

  • @dtryon - 不 - 他正在对他想要设置的选项的标志进行或运算。

标签: c# .net reflection


【解决方案1】:

来自文档:

BindingFlags.SetProperty

指定应设置指定属性的值。为了 COM 属性,指定此绑定标志等效于 指定 PutDispProperty 和 PutRefDispProperty。

BindingFlags.SetPropertyBindingFlags.GetProperty 分别过滤缺少 setter 或 getter 的属性。

要检查是否可以设置属性,请使用CanWrite 属性。

if (pi.CanWrite)
    pi.SetValue(this, valueFromData, null);

【讨论】:

  • 感谢您的信息 - 不能使用 CanWrite,因为这只会显示公共设置器,而且我仍然可以使用私有设置器,因为我是在课堂上执行此操作的。
  • @Alain -- 你确定吗?我刚刚对带有 getter 和 setter 的私有财产进行了测试。该私有属性的 CanWrite 属性返回 true。
  • 我的误解。你是对的 - 两者是可以互换的,因为你的方法不需要空测试,所以它是可取的。
  • 我发现 Silverlight 属性有一个特殊之处,ButtonBase.IsFocused,其中它的程序集内部设置器将为 CanWrite 返回 true。如果您需要避免这种考虑,最好使用pi.GetSetMethod != null
  • fwiw,我遇到了一个只有二传手的属性(说来话长)。所以我也使用了pi.CanRead 来确保我只获得也有getter 的属性。
【解决方案2】:

感谢 ken 提供的信息。它看起来是我可以通过在 LINQ 过滤器中测试 GetSetMethod(true) 来过滤掉它们的最佳解决方案:

// Get all public or private non-static properties declared in this class
// (e.g. excluding inherited properties) that have a getter and setter.
PropertyInfo[] props = this.GetType()
    .GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance |
                   BindingFlags.Public | BindingFlags.NonPublic)
    .Where(p => p.GetGetMethod(true) != null && p.GetSetMethod(true) != null)
    .ToArray();

或者,使用CanReadCanWrite

PropertyInfo[] props = this.GetType()
    .GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance |
                   BindingFlags.Public | BindingFlags.NonPublic)
    .Where(p => p.CanRead && p.CanWrite)
    .ToArray();

我不清楚这些不同的方法是否会对 get/set 方法的不同保护级别产生不同的结果。

【讨论】:

  • 查看我对我的回答的评论。 CanWrite 为我的私有财产返回“真”。对你来说不是同样的方式吗?
【解决方案3】:

我使用这个代码:

    public class CustomBinder
{
    public static void BindModel(object myClass)
    {
        var stringItems = myClass?.GetType()
            .GetProperties()
            .Where(x => x.PropertyType == typeof(string)).ToList();

        if (!(stringItems?.Count > 0)) return;

        foreach (var propertyInfo in stringItems)
        {
            if (propertyInfo.GetValue(myClass, null) != null)
            {
                var val = propertyInfo.GetValue(myClass).ToString().Replace(...);
           if(propertyInfo.CanWrite)
                propertyInfo.SetValue(myClass, val);
            }

        }

    }
    public static void BindModel(List<string> listString)
    {
        if (!(listString?.Count > 0 )) return;

        for (var i = 0; i < listString.Count; i++)
            listString[i] = listString[i].Replace(...);

    }

}

【讨论】:

    【解决方案4】:

    我了解 GetProperties() 方法,因此它会返回具有BindingFlags.GetProperty BindingFlags.SetProperty 的每个属性。
    因此,如果您只想要具有设置器的属性,则必须删除 BindingFlags.GetProperty 标志。但我没有测试它,所以我可能是错的。

    我的答案是-1。所以看来我的回答是错误的。

    【讨论】:

      猜你喜欢
      • 2016-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-16
      • 1970-01-01
      • 1970-01-01
      • 2015-01-16
      • 1970-01-01
      相关资源
      最近更新 更多