简体   繁体   English

反射期间“未找到属性设置方法”错误

[英]"Property set method not found" error during reflection

I'm trying to reflect over some class properties and set them programmatically, but it looks like one of my PropertyInfo filters isn't working:我试图反映一些类属性并以编程方式设置它们,但看起来我的 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 );

I'm getting an error on the line我在线时遇到错误

pi.SetValue(this, valueFromData, null);

Because the property has only a get{} method, no set{} method.因为该属性只有一个get{}方法,没有set{}方法。

My question is, why wasn't this property filtered out of props?我的问题是,为什么这个属性没有从 props 中过滤掉? I thought that was the purpose of BindingFlags.SetProperty.我认为这是 BindingFlags.SetProperty 的目的。

The property not getting filtered out is:未被过滤掉的属性是:

    public String CollTypeDescription
    {
        get { return _CollTypeDescription; }
    }

Note that I want to filter properties that won't work ahead of time because I'm listing them all at once.请注意,我想过滤无法提前使用的属性,因为我将一次性列出所有这些属性。 I don't want to use pi.GetSetMethod() after the fact to determine whether I can use the setter.不想在pi.GetSetMethod()使用pi.GetSetMethod()来确定我是否可以使用 setter。

From the documentation: 从文档:

BindingFlags.SetProperty BindingFlags.SetProperty

Specifies that the value of the specified property should be set. 指定应设置指定属性的值。 For COM properties, specifying this binding flag is equivalent to specifying PutDispProperty and PutRefDispProperty. 对于COM属性,指定此绑定标志等同于指定PutDispProperty和PutRefDispProperty。

BindingFlags.SetProperty and BindingFlags.GetProperty do not filter properties that are missing setters or getters, respectively. BindingFlags.SetPropertyBindingFlags.GetProperty 不会分别过滤缺少setter或getter的属性。

To check if a property can be set, use the CanWrite property. 要检查是否可以设置属性,请使用CanWrite属性。

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

Thanks to ken for the information. 感谢ken的信息。 It looks like the best solution I can get it to filter them out by testing GetSetMethod(true) in a LINQ filter: 它似乎是我可以通过在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();

Alternatively, using CanRead and CanWrite : 或者,使用CanReadCanWrite

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

It's unclear to me whether these different approaches will yield different results for different protection levels of the get/set methods. 我不清楚这些不同的方法是否会对get / set方法的不同保护级别产生不同的结果。

I use this code:我使用这个代码:

    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(...);

    }

}

I understand the GetProperties() method so that it returns every property that has BindingFlags.GetProperty or BindingFlags.SetProperty . 我理解GetProperties()方法,以便它返回具有BindingFlags.GetProperty BindingFlags.SetProperty每个属性。
So if you want only properties that have setters you must remove the BindingFlags.GetProperty flag. 因此,如果您只想要具有setter的属性,则必须删除BindingFlags.GetProperty标志。 But I did not tested it so I can be wrong. 但我没有测试它,所以我错了。

My answer got a -1. 我的回答是-1。 So it seems that my answer is wrong. 所以我的答案似乎错了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM