将具有键值属性的Object []映射到对象的属性,而不使用巨大的讨厌的开关

时间:2016-09-29 15:05:00

标签: c# .net transformation

我有一个Key值的对象数组。

public class KeyValueStore
{
   public string Key {get;set;}
   public string Value {get;set;}
}

这个数组存储了我想要填充的对象的值,如下所示:

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

所以我想将这些键从KeyValueStore映射到Customer属性

public Customer TransformToCustomer(KeyValueStore[] keyValueStore)
{
    var customer = new Customer();

    foreach (var keyValue in keyValueStore)
    {
        switch (keyValue.Key)
        {
            case "Name":
                customer.Name = keyValue.Value;
                break;
            case "Cntry":
                customer.Country = keyValue.Value;
                break;
        }
    }

    return customer;
}

有更好的方法吗?

2 个答案:

答案 0 :(得分:3)

是的,假设目标类型具有无参数构造函数,您可以编写一个执行此操作的泛型方法:

public T CreateAndPopulate<T>(IEnumerable<KeyValueStore> propStore,
                              IDictionary<string, string> mapping = null) 
                             where T:class,new()
{

    T item=new T();
    var type=typeof(T);
    foreach(var kvs in propStore)
    {
        var propName = kvs.Key;
        propName = mapping !=null && mapping.ContainsKey(propName) 
                       ? mapping[propName] 
                       : propName;
        var prop = type.GetProperty(propName);
        if(prop == null) //does the property exist?
        {
            continue;
        }
        var propMethodInfo = prop.GetSetMethod();
        if(propMethodInfo == null) //does it have a set method?
        {
            continue;
        }
        propMethodInfo.Invoke(item, new[]{ kvs.Value });
    }
    return item;
}

并使用它:

IEnumerable<KeyValueStore> propStore = new KeyValueStore[]{
    new KeyValueStore{ Key = "Name", Value = "John" },
    new KeyValueStore{ Key = "Cntry", Value = "UK" }};
var mapping = new Dictionary<string,string>{{ "Cntry", "Country" }};

var customer = CreateAndPopulate<Customer>(propStore, mapping);

答案 1 :(得分:1)

我有另一个建议,很多时候大的开关块表示你遗漏了你的对象设计的东西,正确使用多态可以取代交换机的使用。

首先,我们将重新设计KeyValueStore类以分离ValueStore类,每个类将实现公共接口IValueStore,接口将如下所示:

public interface IValueStore
{
    void AddValueToCostumer(Customer customer);
}

现在NameValueStore将如下所示:

public class NameValueStore : IValueStore
{
    private readonly string _name;       

    public NameValueStore(string name)
    {
        _name = name;
    }

    public void AddValueToCustomer(Costumer costumer)
    {
        customer.Name = _name;
    }
}

和CountryValueStore:

public class CountryValueStore : IValueStore
{
    private readonly string _country;       

    public CountryNameValueStore(string country)
    {
        _country = country;
    }

    public void AddValueToCustomer(Costumer costumer)
    {
        customer.Country = _country;
    }
}

现在你的函数TransformToCustomer看起来像这样:

public Customer TransformToCustomer(IValueStore[] valueStores)
{
    var customer = new Customer();

    foreach (var valueStore in valueStores)
    {
        valueStore.AddValueToCustomer(customer);
    }

    return customer;
}

此解决方案对我来说感觉更加SOLID

希望它有所帮助!