简体   繁体   English

根据属性名称动态分配属性值的最佳方法

[英]Best way to assign property value dynamically based on the property name

I have a List that I am iterating through. 我有一个要迭代的列表。

Inside the List<> are Argument classes which contain two properties 'PropertyName' and 'Value' List <>内部是Argument类,其中包含两个属性'PropertyName'和'Value'

What I need to do is iterate through the collection of Arguments and assign the Value of that Argument to the Property (with the same name as current Argument) of a different class. 我需要做的是遍历参数的集合,并将该参数的值分配给不同类的属性(与当前参数同名)。

Example: 例:

Argument:
     PropertyName: ClientID
            Value: 1234
Members Class:
     ClientID = {Argument Value here}

I hope this makes sense. 我希望这是有道理的。 I have a way of doing it, hard coding the properties of my class and matching it up with the Argument list. 我有一种方法,可以对类的属性进行硬编码,并将其与Argument列表匹配。

Something like: 就像是:

foreach(var arg in List<Argument>)
{
    Members.ClientID = arg.Find(x => compareName(x, "ClientID")).Value;
    //where compareName just does a simple string.Compare
}

But what would the BEST way be for something like this? 但是对于这样的东西,最好的方式是什么?

EDIT: Sorry about this guys and thanks for the replies so far. 编辑:对不起,这些家伙,并感谢到目前为止的答复。 Here is what I didn't mention and might make a difference. 这是我未提及的内容,可能会有所作为。

Each argument is a different property for the same class. 每个参数是同一类的不同属性。 I am iterating through the List and each one in there will be for the same Members class I have to populate. 我正在遍历列表,每个列表中我必须填充相同的成员类。

I wanted to mention this because im thinking in the foreach I might have to use a switch to determine what 'PropertyName' I have for that Argument. 我想提到这一点,因为我想在foreach中可能必须使用开关来确定该参数的“ PropertyName”。 ClientID is one of them but I believe there are 14 total properties in the Members class that need populated from the Collection. ClientID是其中之一,但我认为需要从Collection中填充的Members类中共有14个属性。

Does that change things? 这会改变一切吗?

Thanks again 再次感谢

public object this[string propertyName]
{
    get
    {
        Type myType = typeof(UserConfiguration);
        PropertyInfo myPropInfo = myType.GetProperty(propertyName);
        return myPropInfo.GetValue(this, null);
    }
    set
    {
        Type myType = typeof(UserConfiguration);
        PropertyInfo myPropInfo = myType.GetProperty(propertyName);
        myPropInfo.SetValue(this, value, null);
    }
}

Then you can get/set properties within the class using 然后您可以使用以下方法在类中获取/设置属性

myClassInstance["ClientId"] = myValue;

If I understand what you're asking, perhaps something like this will work for you: 如果我了解您的要求,也许类似的方法将对您有用:

var argDict = arguments.ToDictionary(x => x.PropertyName, x => x.Value);
Members.ClientID = argDict["ClientID"];
...

If you need to do some special comparison on the keys you can provide the dictionary it's own IEqualityComparer . 如果您需要对键进行一些特殊的比较,则可以提供它自己的IEqualityComparer字典。 For example, this will make sure that the keys are treated case-insensitively: 例如,这将确保键不区分大小写:

var argDict = arguments.ToDictionary(x => x.PropertyName, x => x.Value, 
                                     StringComparer.OrdinalIgnoreCase);

This will work fine as long as the arguments list contains all the values you need. 只要参数列表包含所需的所有值,此方法就可以正常工作。 If some arguments might be missing, you'd have to do something like this: 如果可能缺少一些参数,则必须执行以下操作:

if (argDict.ContainsKey("ClientID")) { 
    Members.ClientID = argDict["ClientID"];
}

Or possibly something like this: 或者可能是这样的:

Members.ClientID = argDict.ContainsKey("ClientID") ? argDict["ClientID"] : "DefaultValue";

I think that your basic intent is to set the value of a property on a target object based on the property name. 我认为您的基本意图是根据属性名称在目标对象上设置属性的值。 Since you did not provide the Argument class I will assume it is defined like this: 由于您未提供Argument类,因此我将假定其定义如下:

public class Argument
{
    public string PropertyName{get; set;}
    public object PropertyValue{get;set;}
}

Further assume you have the class Blah defined like this: 进一步假设您具有这样定义的Blah类:

public class Blah
{
    public string AString{get; set;}
    public int AnInt{get; set;}
    public DirectoryInfo ADirInfo{get; set;}
}

If you wish to assign to the properties of a Blah object based on the values in List<Argument> you can do so like this: 如果希望基于List<Argument>的值来分配Blah对象的属性,则可以这样:

List<Argument> arguments = new List<Argument>
{
    new Argument(){PropertyName = "AString", PropertyValue = "this is a string"},
    new Argument(){PropertyName = "AnInt", PropertyValue = 1729},
    new Argument(){PropertyName = "ADirInfo", PropertyValue = new DirectoryInfo(@"c:\logs")}
};

Blah b = new Blah();
Type blahType = b.GetType();
foreach(Argument arg in arguments)
{
    PropertyInfo prop = blahType.GetProperty(arg.PropertyName);
    // If prop == null then GetProperty() couldn't find a property by that name.  Either it doesn't exist, it's not public, or it's defined on a parent class
    if(prop != null) 
    {
        prop.SetValue(b, arg.PropertyValue);
    }
}

This depends on the objects stored in Argument.PropertyValue having the same type as the property of Blah referred to by Argument.PropertyName (or there must be an implicit type conversion available). 这取决于存储在Argument.PropertyValue中的对象,该对象具有与Argument.PropertyName引用的Blah属性相同的类型(或者必须有隐式类型转换)。 For example, if you alter the List<Argument> as follows: 例如,如果按如下所示更改List<Argument>

List<Argument> arguments = new List<Argument>
{
    new Argument(){PropertyName = "AString", PropertyValue = "this is a string"},
    new Argument(){PropertyName = "AnInt", PropertyValue = 1729},
    new Argument(){PropertyName = "ADirInfo", PropertyValue = "foo"}
};

you will now get an exception when attempting to assign to Blah.ADirInfo: Object of type 'System.String' cannot be converted to type 'System.IO.DirectoryInfo' 您现在在尝试分配给Blah.ADirInfo时会遇到异常: Object of type 'System.String' cannot be converted to type 'System.IO.DirectoryInfo'

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

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