【问题标题】:How to convert dynamic list List<object> to object list List<Customer>如何将动态列表 List<object> 转换为对象列表 List<Customer>
【发布时间】:2018-12-27 07:23:34
【问题描述】:

我正在尝试将我的动态列表 List&lt;object&gt; 转换为 List&lt;Customer&gt;。 动态列表共有 10 个属性(Id、Name、PhoneNo、Address、SecodaryPhone、Email 等),Customer 类只有 Id、Name 和 PhoneNo。 我想转换列表,以便它将复制具有映射属性的列表。

我不能使用动态属性的名称,因为这可以像存储其他类型一样使用任何其他类型,比如产品。

【问题讨论】:

  • AutoMapper 呢?
  • 使用listofObject.Select(x =&gt; new Customer { Id = x.Id, Name = x.Name, PhoneNo = x.PhoneNo }).ToList();怎么样?但是在尝试上面建议的代码之前,您需要展示您转换这两个列表的努力。
  • 您的 :dynamic list" 实际上是 List&lt;dynamic&gt; 还是您的意思是成员的实际类型可能在不同时间有所不同?或者列表包含多种不同的类型?你的最后一句话是什么?什么意思?

标签: c# asp.net-mvc entity-framework linq


【解决方案1】:

安装 AutoMapper NuGet 包。然后你可以像这样投射你的列表:

class Program
{
    static void Main(string[] args)
    {
        var config = new MapperConfiguration(cfg => { });
        var mapper = config.CreateMapper();

        dynamic person = new { Name = "John", Id = 10 };

        var people = new List<dynamic>() { person };
        var cusomters = people.Select(p => mapper.Map<Customer>(p)).ToList();
    }
}

class Customer
{
    public string Name { get; set; }
}

编辑

或者,如果您不想使用 AutoMapper,您可以尝试以下方法:

    class Program
{
    static void Main(string[] args)
    {
        dynamic people = new { Name = "John", Id = 10 };

        var list = new List<dynamic>() { people };
        var result = list.Select(p => new Customer(p)).ToList();
    }
}

class Customer
{
    public string Name { get; set; }

    public Customer(dynamic arg)
    {
        Name = arg.Name;
    }
}

【讨论】:

    【解决方案2】:

    使用一些扩展来简化MemberInfo 的使用:

    // ***
    // *** Type Extensions
    // ***
    public static List<MemberInfo> GetPropertiesOrFields(this Type t, BindingFlags bf = BindingFlags.Public | BindingFlags.Instance) =>
        t.GetMembers(bf).Where(mi => mi.MemberType == MemberTypes.Field | mi.MemberType == MemberTypes.Property).ToList();
    
    // ***
    // *** MemberInfo Extensions
    // ***
    public static object GetValue(this MemberInfo member, object srcObject) {
        switch (member) {
            case FieldInfo mfi:
                return mfi.GetValue(srcObject);
            case PropertyInfo mpi:
                return mpi.GetValue(srcObject);
            default:
                throw new ArgumentException("MemberInfo must be of type FieldInfo or PropertyInfo", nameof(member));
        }
    }
    public static T GetValue<T>(this MemberInfo member, object srcObject) => (T)member.GetValue(srcObject);
    
    public static void SetValue<T>(this MemberInfo member, object destObject, T value) {
        switch (member) {
            case FieldInfo mfi:
                mfi.SetValue(destObject, value);
                break;
            case PropertyInfo mpi:
                mpi.SetValue(destObject, value);
                break;
            default:
                throw new ArgumentException("MemberInfo must be of type FieldInfo or PropertyInfo", nameof(member));
        }
    }
    

    您可以使用此扩展将匹配的对象成员值复制到另一种类型:

    // Convert any object to another Type by copying over common properties or fields
    public static T ToType<T>(this object obj) where T : new() {
        var ansObj = new T();
        var ansFields = typeof(T).GetPropertiesOrFields().ToDictionary(pf => pf.Name);
    
        foreach (var prop in obj.GetType().GetPropertiesOrFields())
            if (ansFields.TryGetValue(prop.Name, out var destpf))
                destpf.SetValue(ansObj, prop.GetValue(obj));
    
        return ansObj;
    }
    

    所以你的最终结果是:

    var ans = sourceList.Select(m => m.ToType<Customer>()).ToList();
    

    但我认为使用接口并拥有一个通用的基本接口会更好:

    interface IIDBase {
        int Id { get; set; }
        string Name { get; set; }
        string PhoneNo { get; set; }
    }
    
    public class Customer {
        public int Id { get; set; }
        public string Name { get; set; }
        public string PhoneNo { get; set; }
    }
    
    public class Products : IIDBase {
        public int Id { get; set; }
        public string Name { get; set; }
        public string PhoneNo { get; set; }
        // ...
    }
    

    然后您只需转换为 List&lt;IIDBase&gt;:

    var ans = sourceList.Cast<IIDBase>().Select(m => new Customer {
                  Id = m.Id,
                  Name = m.Name,
                  PhoneNo = m.PhoneNo
              });
    

    【讨论】:

      【解决方案3】:

      如果您可以使用dynamic,这应该可以工作。

      var list = new List<object>(new [] 
      {
          new DynamicObject {Id = $"{1}", Name = $"Name{1}", PhoneNo = $"555-000{1}-1234"},
          new DynamicObject {Id = $"{2}", Name = $"Name{2}", PhoneNo = $"555-000{2}-1234"},
          new DynamicObject {Id = $"{3}", Name = $"Name{3}", PhoneNo = $"555-000{3}-1234"},
      });
      var customers = ((IEnumerable<dynamic>)list).Select(x => new Customer{ Id = x.Id, Name = x.Name, PhoneNo = x.PhoneNo}).ToArray();
      Customer customer = customers.First();
      
      
      
      class DynamicObject
      {
          public string Id { get; set; }
          public string Name { get; set; }
          public string PhoneNo { get; set; }
          public string Address { get; set; }
          public string SecodaryPhone { get; set; }
          public string Email { get; set; }
      }
      
      class Customer
      {
          public string Id { get; set; }
          public string Name { get; set; }
          public string PhoneNo { get; set; }
      }
      

      【讨论】:

        猜你喜欢
        • 2020-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-27
        • 2012-09-18
        • 2017-07-04
        相关资源
        最近更新 更多