使用反射将List <dynamic>设置为List <t> </t> </dynamic>

时间:2014-11-17 10:05:15

标签: c# dynamic reflection

说,我在课堂上有这些属性:

public class Example
{
    public List<Toyota> listToyota; 
    public List<Honda> listHonda; 
    public List<Huyndai> listHuyndai; 
    ... 
    ... 
}

如果有新的汽车品牌,将会有更多的房产。每个品牌都是一张桌子。

通常,我会这样做以从表中获取数据:

Example result = new Example();
switch (brandname)
{
    case "Toyota":
        result.listToyota = * select table from context * ; 
        break;
    case "Honda":
        result.listHonda = * select table from context * ; 
        break;
        ...
}

此外,当有新品牌时,我将不得不添加更多代码。我发现这非常烦人/耗时,并决定转向动态方法。我已成功地动态获取表格:

tblName = "Toyota"; 
IEnumerable<dynamic> table = typeof(MyContext).GetProperty(tblName).GetValue(context, null) as IEnumerable<dynamic>;

但我无法动态设置属性值,在本例中为listToyota

query = (from a in table select a).ToList() as List<dynamic>;
SetPropertyValue(result, "listToyota", query);

我收到了这个错误:

  

类型为'System.Collections.Generic.List1 [System.Object]'的对象   无法转换为类型   'System.Collections.Generic.List1 [丰田]'。

SetPropertyValue使用System.Reflection是一个非常简单的函数:

static void SetPropertyValue(object p, string propName, object value)
{
    Type t = p.GetType();

    System.Reflection.PropertyInfo info = t.GetProperty(propName);

    if (info == null)
        return;
    if (!info.CanWrite)
        return;
    info.SetValue(p, value, null);
}

非常感谢任何建议!

2 个答案:

答案 0 :(得分:2)

请尝试这样的事情

static void SetPropertyValue(object p, string propName, object value)
{
    Type t = p.GetType();

    System.Reflection.PropertyInfo info = t.GetProperty(propName);

    if (info == null)
        return;
    if (!info.CanWrite)
        return;

    var elemtype = info.PropertyType.GetElementType();
    var castmethod = typeof(Enumerable).GetMethod("Cast", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(elemtype);
    var tolist = typeof(Enumerable).GetMethod("ToList", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(elemtype);

    var collection = castmethod.Invoke(null, new object[] { value });
    var list = tolist.Invoke(null, new object[] { collection });

    info.SetValue(p, list, null);
}

答案 1 :(得分:-1)

我认为主要问题是您的软件设计。我不会以这种方式使用动态。

  1. 我会创建一个Brand-Class。如果你想使用动态,尝试这样的事情:

    public class DynamicBrand : DynamicObject
    {
        private IDictionary<string, object> myDynamicValues;
    
        public DynamicBrand()
                : base()
        {
            myDynamicValues = new Dictionary<string, object>();
        }
    
        public void AddMember(string Name, object Value)
        {
            if (!myDynamicValues.ContainsKey(Name.Trim().ToLower()))
            {
                myDynamicValues.Add(Name.ToLower().Trim(), Value);
            }
            else
            {
                throw new Exception("The Member with the Name: " + Name + " already exists!");
            }
        }
        public override bool TrySetMember(SetMemberBinder Binder, object Value)
        {
            if (myDynamicValues.ContainsKey(Binder.Name.ToLower()))
            {
                myDynamicValues[Binder.Name.ToLower()] = Value;
                return true;
            }
            else
            {
                myDynamicValues.Add(Binder.Name.ToLower(), Value);
            }
    
            return true;
        }
    
        publc override bool TryGetMember(GetMemberBinder Binder, out object Result)
        {
            if (myDynamicValues.ContainsKey(Binder.Name.ToLower()))
            {
                Result = myDynamicValues[Binder.Name.ToLower()];
                return true;
            }
            else
            {            
                Result = null;
                return false;
             }
        }
    
  2. 我会改变你的示例类

    public class Example
    {
        // string = brand-name; list = list of dynamic brand items
        public Dictionary<string, List<DynamicBrand>> brands;
    }
    
  3. 当您填写数据时,只需在品牌列表中添加一个新的动态品牌,然后只需添加您需要的成员。

  4. 编辑:动态不是解决您问题的绝佳解决方案。我会考虑一个完全不同的结构。