Как преобразовать динамический список List <object>в список объектов List <Customer> - PullRequest
0 голосов
/ 27 декабря 2018

Я пытаюсь преобразовать мой динамический список List<object> в List<Customer>.Динамический список имеет всего 10 свойств (Id, Name, PhoneNo, Address, SecodaryPhone, Email и т. Д.), А в классе Customer есть только Id, Name и PhoneNo.Я хочу преобразовать список, чтобы он копировал список со свойствами сопоставления.

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

Ответы [ 3 ]

0 голосов
/ 27 декабря 2018

Использование некоторых расширений для упрощения работы с 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<IIDBase>:

var ans = sourceList.Cast<IIDBase>().Select(m => new Customer {
              Id = m.Id,
              Name = m.Name,
              PhoneNo = m.PhoneNo
          });
0 голосов
/ 27 декабря 2018

Это должно работать, если вы можете использовать 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; }
}
0 голосов
/ 27 декабря 2018

Установите пакет 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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...