2013-12-06 4 views
1

У меня есть список, который я повторяю.Лучший способ присвоить значение свойства динамически на основе имени свойства

Внутри списка <> классы аргументов, которые содержат два свойства «ИмениСвойства» и «Value»

Что мне нужно сделать, это перебирать коллекцию Аргументы и присвоить значение этого аргумента к собственности (с тем же именем, что и текущий аргумент) другого класса.

Пример:

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

Я надеюсь, что это имеет смысл. У меня есть способ сделать это, жестко кодируя свойства моего класса и сопоставляя его с списком аргументов.

Что-то вроде:

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

Но что лучший способ быть что-то вроде этого?

EDIT: Извините, об этом, ребята, и спасибо за ответы. Вот что я не упоминал и мог бы изменить ситуацию.

Каждый аргумент является другим свойством для того же класса. Я повторяю список, и каждый из них будет в том же классе членов, который я должен заполнить.

Я хотел упомянуть об этом, потому что, думая в foreach, мне, возможно, придется использовать переключатель, чтобы определить, что у меня есть «PropertyName» для этого аргумента. ClientID является одним из них, но я считаю, что в классе Members есть 14 общих свойств, которые нужно заполнить из коллекции.

Это что-то меняет?

Еще раз спасибо

+0

могли бы вы опубликовать определение класса 'Argument'? – Odrade

ответ

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, имеющие тот же тип, что и свойство Blah, на которое ссылается Argument.PropertyName (или должно быть доступно неявное преобразование типа). Например, если вы измените 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'

+0

После того, как вы пробовали каждый из этих предложений, это был тот, который сделал это для меня. @ p.w.s.g Я ценю ответ, и он был прав, и дал мне то, что мне было нужно, однако Одраде было на месте и разрешило мне проходить через сбор и заполнить мой класс так, как мне было нужно. Спасибо всем за ответ и время. Хороших выходных. – DeepToot

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"; 
+0

Спасибо за ответ pswg, позвольте мне добавить что-то к моему OP, я пропустил важную информацию, необходимую для ответа. – DeepToot

+0

@DeepToot Да, именно там я и думал, что вы занимаетесь этим вопросом. В основном вместо цикла foreach + switch вы можете преобразовать все аргументы в словарь за один проход, а затем эффективно искать значения по их ключам. –

+0

Хорошо, это звучит хорошо. Позвольте мне попробовать и посмотреть, дает ли он мне то, что мне нужно. Я ценю ответ и помощь. – DeepToot

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; 
+0

Благодарю вас за ответ. Я также дам этому попытку и посмотрю, дает ли она мне то, что мне нужно. Спасибо за время. – DeepToot

Смежные вопросы