14

これを行う方法はありますか?オブジェクトのプロパティが存在するかどうかをテストしようとしています。存在する場合は、それに値を設定したいと考えています。(もし本当なら、完全なアイデアが悪いのかもしれません - なぜですか?)

class Info
{
    public string X1{ set; get; }
    public string X2{ set; get; }
    public string X3{ set; get; }
}

Dictionary<string, string> values = new Dictionary<string, string>();
values.Add("X1","blah1");
values.Add("X2","blah2");
values.Add("NotThere","blah3");

Info info = new Info();

foreach (var item in values)
{
  string propertyName = item.Key;
  string value = item.Value;
  if (info.GetType().GetProperty(propertyName) != null)  //this probably works
  {
        info.propertyName = value; //this doesn't, how to set it?
  }
}
4

4 に答える 4

33

はい、 PropertyInfo.SetValueメソッドを探しています。

var propInfo = info.GetType().GetProperty(propertyName);
if (propInfo != null)
{
    propInfo.SetValue(info, value, null);
}
于 2012-08-06T07:51:40.933 に答える
9
var propertyInfo = info.GetType().GetProperty(propertyName);
if (propertyInfo != null)  //this probably works. Yes it is
  {
        propertyInfo.SetValue(info, value, null);
  }
于 2012-08-06T07:52:34.207 に答える
4

SetValueプロパティでメソッドを呼び出す必要があります。

var property = info.GetType().GetProperty(propertyName);
if (property != null)
{
    property.SetValue(info, value, null); 
}
于 2012-08-06T07:52:14.607 に答える
1

毎回リフレクションを使用するのは少し遅いと思うので、その初期化を複数回行う場合は、式ツリーを使用できます。ただし、辞書には、初期化するプロパティの順序が同じである必要があります。

可能なコード

class Info
{
    public string X1 { set; get; }
    public string X2 { set; get; }
    public int X3 { set; get; }
    private Action<Info, List<object>> initAction;

    public void Init(Dictionary<string, object> initDict)
    {
        //on first usage we deal with reflection and build expression tree to init properties
        if (initAction==null)
        {
            ParameterExpression targetInstanceExpression = Expression.Parameter(this.GetType());
            ParameterExpression valuesExpression = Expression.Parameter(typeof(List<object>));
            ParameterExpression value = Expression.Variable(typeof(object));
            ParameterExpression enumerator = Expression.Variable(typeof(IEnumerator));

            var expList = new List<Expression>();
            expList.Add(Expression.Assign(enumerator, Expression.TypeAs(Expression.Call(valuesExpression, "GetEnumerator", null),typeof(IEnumerator))));
            foreach (var initRecord in initDict)
            {
                Expression moveNextExp = Expression.Call(enumerator, "MoveNext", null);
                expList.Add(moveNextExp);
                Type type = initRecord.Value.GetType();
                expList.Add(Expression.Assign(value, Expression.PropertyOrField(enumerator, "Current")));
                Expression assignExp = GetPropAssigner(initRecord.Key, type, targetInstanceExpression, value);
                expList.Add(assignExp);
            }
            Expression block = Expression.Block
            (
                 new[] { value, enumerator },
                 expList
            );
            //compile epression tree and get init action 
            initAction = Expression.Lambda<Action<Info, List<object>>>(block, targetInstanceExpression, valuesExpression).Compile();
        }
        initAction(this, initDict.Values.ToList());
    }
    //little method to create property assigner
    public static Expression GetPropAssigner(string propName, Type type,
         ParameterExpression targetInstanceExp, ParameterExpression valueExp)
    {
        MemberExpression fieldExp = Expression.PropertyOrField(targetInstanceExp, propName);
        BinaryExpression assignExp = Expression.Assign(fieldExp, type.IsValueType ? Expression.Unbox(valueExp, type) : Expression.TypeAs(valueExp, type));
        return assignExp;
    }
}

使用法:

var values = new Dictionary<string, object>();
            values.Add("X1", "blah1");
            values.Add("X2", "blah2");
            values.Add("X3", 8);


Info info = new Info();
info.Init(values);
于 2012-08-06T09:51:46.703 に答える