反射和设置属性?

发布于 2024-11-04 03:30:08 字数 1236 浏览 0 评论 0原文

所以,我有一个从另一个类继承的对象类。但是,每当我尝试使用反射使用 InvokeMember 方法设置子类时,它都会说 Method/Member 不存在。我错过了什么吗?

namespace Group {
    public class Person {
        public Guid PersonId { get; set; }
        public string FirstName { get; set; }

        public void Load(NameValueCollection fields) {
             Type classType = this.GetType();

             PropertyInfo[] properties = classType.GetProperties();

             foreach(PropertyInfo property in properties)
             {
                 for(int x = 0; x < fields.Count; x++)
                 {
                     if (fields.Keys[x] != property.Name) continue;

                     classType.InvokeMember(property.Name, BindingFlags.Instance | BindingFlags.SetProperty, Type.DefaultBinder, this, new object[] { fields[x] });
                     break;
                 }
             }
       }
}

namespace Group {
    public class VIPPerson : Person { }
}

下面的代码调用上面的类:

function someMethod() {
    NameValueCollection collection = new NameValueCollection();
    collection.Add("FirstName", "Mark");

    VIPPerson person = new VIPPerson();
    person.Load(collection);
}

为什么 InvokeMember 抛出一个错误说该属性不存在?有什么帮助吗?

So, I have a object class that is inherited from another class. However, whenever I try to set the child class with the InvokeMember method using reflection, it says that Method/Member doesn't exist. Am I missing something?

namespace Group {
    public class Person {
        public Guid PersonId { get; set; }
        public string FirstName { get; set; }

        public void Load(NameValueCollection fields) {
             Type classType = this.GetType();

             PropertyInfo[] properties = classType.GetProperties();

             foreach(PropertyInfo property in properties)
             {
                 for(int x = 0; x < fields.Count; x++)
                 {
                     if (fields.Keys[x] != property.Name) continue;

                     classType.InvokeMember(property.Name, BindingFlags.Instance | BindingFlags.SetProperty, Type.DefaultBinder, this, new object[] { fields[x] });
                     break;
                 }
             }
       }
}

namespace Group {
    public class VIPPerson : Person { }
}

The following code calls the above class:

function someMethod() {
    NameValueCollection collection = new NameValueCollection();
    collection.Add("FirstName", "Mark");

    VIPPerson person = new VIPPerson();
    person.Load(collection);
}

Any help why the InvokeMember is throwing an error that says the property doesn't exist?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

青衫负雪 2024-11-11 03:30:08

以下是我使用 SetValue 从 xml 文件中读取值的方法。

        //--- Get Object Properties
        PropertyDescriptorCollection props = TypeDescriptor.GetProperties(targetComponent);

        foreach (var xmlProperty in propertiesFromXML)
        {
            var propertyName = xmlProperty.Name.ToString();
            var propertyDescriptor = props[propertyName];

            if (propertyDescriptor == null)
            {
                // Property does not exist, create one anyways?
            }
            else
            {
                propertyDescriptor.SetValue(targetComponent, Convert.ChangeType(xmlProperty.Value, propertyDescriptor.PropertyType));
            }

        }

Here's how I do it using SetValue reading the value out of an xml file.

        //--- Get Object Properties
        PropertyDescriptorCollection props = TypeDescriptor.GetProperties(targetComponent);

        foreach (var xmlProperty in propertiesFromXML)
        {
            var propertyName = xmlProperty.Name.ToString();
            var propertyDescriptor = props[propertyName];

            if (propertyDescriptor == null)
            {
                // Property does not exist, create one anyways?
            }
            else
            {
                propertyDescriptor.SetValue(targetComponent, Convert.ChangeType(xmlProperty.Value, propertyDescriptor.PropertyType));
            }

        }
尸血腥色 2024-11-11 03:30:08

如果您在执行 this.gettype() 的地方尝试这段小代码片段,

您就会明白发生了什么:

        Type t = this.GetType();

        while (t.Name != typeof(Object).Name) {
            Console.WriteLine(t.Name);
            t = t.BaseType;
        }
        Console.WriteLine(t.Name);

基本上您正在调用不同类型的某些东西......

Type t = typeof(Person);

并且可能

(Person)this

在调用时?因为调用需要一个装箱类型的对象...

编辑:我没有发现您正在使用属性执行此操作...您应该使用调用的 Setvalue insetad :)

如果您确实希望像这样调用它,请使用

classType.InvokeMember(property.GetSetMethod().Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, Type.DefaultBinder, (Person)this, new object[] { fields[x] });

: .NET 中的属性设置方法目前为“set_PropertyName”...
您在代码中看不到这一点,但编译会用两种方法编译属性,一种用于设置,一种用于获取(假设它不是只读,那么您只能获取 Get)

If you try this small snippet of code in the place where you do this.gettype()

you will understand what is going on:

        Type t = this.GetType();

        while (t.Name != typeof(Object).Name) {
            Console.WriteLine(t.Name);
            t = t.BaseType;
        }
        Console.WriteLine(t.Name);

Basically you are invoking something on a different type...

Type t = typeof(Person);

and probably

(Person)this

when invoking? because the invoke takes an object that boxes the type...

EDIT: I didnt catch that you are doing this with properties... you should use the Setvalue insetad of invoking :)

If you really wish to invoke it like this use:

classType.InvokeMember(property.GetSetMethod().Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, Type.DefaultBinder, (Person)this, new object[] { fields[x] });

The property set method in .NET is for now "set_PropertyName"...
You don't see this in code, but compilation compiles properties in two methods, one for set and one for get (assuming it is not readonly, then you get only the Get)

浪漫人生路 2024-11-11 03:30:08

为什么不直接调用SetValue?

property.SetValue(this, fields[x], null);

您可以通过 PropertyInfo 对象设置属性。

Why arent you calling SetValue directly?

property.SetValue(this, fields[x], null);

You can set the property via the PropertyInfo object.

怎言笑 2024-11-11 03:30:08

由于您要设置属性值,因此不使用 InvokeMember,那么使用 SetValue 怎么样?

property.SetValue(this, fields[x], null);

Instead of using InvokeMember, since you're setting the property value, how about using SetValue?

property.SetValue(this, fields[x], null);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文