简体   繁体   English

使用反射设置列表 <dynamic> 列出 <T>

[英]Using reflection to set List<dynamic> to List<T>

Say, I have these properties in a class : 说,我在一个类中有这些属性:

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

And there will be more properties if there are new car brands. 如果有新的汽车品牌,将会有更多的物业。 Each brand is a table. 每个品牌都是一张桌子。

Normally, I would do this to get the data from tables : 通常,我会这样做以从表中获取数据:

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

Also, I'll have to add more code when there are new brands. 另外,当有新品牌时,我将不得不添加更多代码。 I found this very annoying/time-consuming and decided to switch to a dynamic approach. 我发现这很烦人/很耗时,因此决定改用动态方法。 I've sucessfully get the tables dynamically : 我成功地动态获取了表:

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

But I failed to dynamically set the property value, in this example, is listToyota : 但是我无法动态设置属性值,在本例中为listToyota

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

I got this error : 我收到此错误:

Object of type 'System.Collections.Generic.List1[System.Object]' cannot be converted to type 'System.Collections.Generic.List1[Toyota]'. 类型“ System.Collections.Generic.List1 [System.Object]”的对象不能转换为类型“ System.Collections.Generic.List1 [Toyota]”。

SetPropertyValue is a very simple function using System.Reflection : 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);
}

Any advices are greatly appreciated! 任何建议,不胜感激!

Please try something like this 请尝试这样的事情

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

I think the main problem is your software design. 我认为主要问题是您的软件设计。 I wouldn't use dynamic this way. 我不会以这种方式使用动态。

  1. I would create a Brand-Class. 我会创建一个品牌级的。 If you want to use dynamic, try something like this: 如果要使用动态,请尝试以下操作:

     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. I would change your example class 我会改变你的榜样

     public class Example { // string = brand-name; list = list of dynamic brand items public Dictionary<string, List<DynamicBrand>> brands; } 
  3. Whenyou fill your data, just add a new dynamic brand to your brands-list and simply add the member you need. 填写数据时,只需在品牌列表中添加一个新的动态品牌,然后只需添加所需的成员即可。

EDIT : Dynamic isn't a very nice solution for your problem. 编辑 :动态不是一个很好的解决方案,为您的问题。 I would think about a completly different structure. 我会考虑完全不同的结构。

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

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