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

时间:2013-12-06 22:18:55

标签: c#

我有一个我正在迭代的列表。

列表内<>是Argument类,包含两个属性'PropertyName'和'Value'

我需要做的是遍历Arguments集合并将该Argument的Value赋值给另一个类的Property(与当前Argument同名)。

示例:

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

我希望这是有道理的。我有办法做到这一点,硬编码我的类的属性,并将其与Argument列表匹配。

类似的东西:

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

但是最好的方法是什么呢?

编辑:对这个家伙感到抱歉,感谢你们的回复。这是我没有提到的,可能会有所作为。

每个参数都是同一个类的不同属性。我正在遍历列表,每个人都将在同一个我必须填充的成员类中。

我想提一下,因为我在foreach中思考,我可能不得不使用开关来确定我对该参数的'PropertyName'。 ClientID就是其中之一,但我相信在Member类中总共有14个属性需要从Collection中填充。

这会改变一些事情吗?

再次感谢

3 个答案:

答案 0 :(得分:3)

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);
    }
}

然后你可以使用

获取/设置类中的属性
myClassInstance["ClientId"] = myValue;

答案 1 :(得分:2)

如果我理解你的要求,也许这样的事情对你有用:

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

如果您需要对键进行一些特殊比较,您可以提供它自己的词典IEqualityComparer。例如,这将确保密钥处理不区分大小写:

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

只要参数列表包含您需要的所有值,这将正常工作。如果可能缺少某些参数,则必须执行以下操作:

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

或者可能是这样的:

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

答案 2 :(得分:0)

我认为您的基本意图是根据属性名称在目标对象上设置属性的值。由于您没有提供Argument类,我将假设它的定义如下:

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

进一步假设你有这样定义的类Blah

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

如果您希望根据Blah中的值分配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 = 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);
    }
}

这取决于存储在Argument.PropertyValue中的对象,其类型与Argument.PropertyName引用的Blah属性相同(或者必须有可用的隐式类型转换)。例如,如果您更改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"}
};

尝试分配给Blah.ADirInfo时,您将收到异常:Object of type 'System.String' cannot be converted to type 'System.IO.DirectoryInfo'