Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将具有键值属性的对象[]映射到对象';s属性,而不使用巨大的讨厌的开关_C#_.net_Transformation - Fatal编程技术网

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

C# 将具有键值属性的对象[]映射到对象';s属性,而不使用巨大的讨厌的开关,c#,.net,transformation,C#,.net,Transformation,我有一个键值的对象数组 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} } public interface IValue

我有一个键值的对象数组

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}
}
public interface IValueStore
{
    void AddValueToCostumer(Customer customer);
}
public class NameValueStore : IValueStore
{
    private readonly string _name;       

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

    public void AddValueToCustomer(Costumer costumer)
    {
        customer.Name = _name;
    }
}
public Customer TransformToCustomer(IValueStore[] valueStores)
{
    var customer = new Customer();

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

    return customer;
}
所以我想将这些键从KeyValueStore映射到客户属性

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

有更好的方法吗?

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

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;
}
public T创建并填充(IEnumerable propStore,
IDictionary映射=空)
其中T:class,new()
{
T项=新的T();
var类型=类型(T);
foreach(propStore中的var kvs)
{
var propName=kvs.Key;
propName=mapping!=null&&mapping.ContainsKey(propName)
?映射[propName]
:propName;
var prop=type.GetProperty(propName);
if(prop==null)//属性是否存在?
{
继续;
}
var propMethodInfo=prop.GetSetMethod();
if(propMethodInfo==null)//它是否有一个set方法?
{
继续;
}
propMethodInfo.Invoke(项,新[]{kvs.Value});
}
退货项目;
}
并使用它:

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);
IEnumerable propStore=新的KeyValueStore[]{
新的KeyValueStore{Key=“Name”,Value=“John”},
新的KeyValueStore{Key=“Cntry”,Value=“UK”};
变量映射=新字典{{“Cntry”,“Country”};
var customer=CreateAndPopulate(propStore,映射);

我还有另一个建议,很多时候,大开关块表示您的对象desigen缺少了一些东西,正确使用多态性可以取代开关的使用

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

public class Customer
{
   public string Name {get;set;}
   public string Country {get;set}
}
public interface IValueStore
{
    void AddValueToCostumer(Customer customer);
}
public class NameValueStore : IValueStore
{
    private readonly string _name;       

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

    public void AddValueToCustomer(Costumer costumer)
    {
        customer.Name = _name;
    }
}
public Customer TransformToCustomer(IValueStore[] valueStores)
{
    var customer = new Customer();

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

    return customer;
}
现在,NameValueStore将如下所示:

public class Customer
{
   public string Name {get;set;}
   public string Country {get;set}
}
public interface IValueStore
{
    void AddValueToCostumer(Customer customer);
}
public class NameValueStore : IValueStore
{
    private readonly string _name;       

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

    public void AddValueToCustomer(Costumer costumer)
    {
        customer.Name = _name;
    }
}
public Customer TransformToCustomer(IValueStore[] valueStores)
{
    var customer = new Customer();

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

    return customer;
}
和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 class Customer
{
   public string Name {get;set;}
   public string Country {get;set}
}
public interface IValueStore
{
    void AddValueToCostumer(Customer customer);
}
public class NameValueStore : IValueStore
{
    private readonly string _name;       

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

    public void AddValueToCustomer(Costumer costumer)
    {
        customer.Name = _name;
    }
}
public Customer TransformToCustomer(IValueStore[] valueStores)
{
    var customer = new Customer();

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

    return customer;
}
这个解决方案让我感觉好多了


希望有帮助

快速看一眼,很难避免任何类型的切换/查找代码,因为您的键不是与属性对齐的事件。我的意思是
“Cntry”!=Country
假设键实际上是属性名,没有拼写错误,看看这里:你为什么要用你的
KeyValueStore
类在这里重新发明
字典呢?你猜对了Mark C,我添加了“拼写错误”来说明这种情况也可能发生。这不是我的选择。我的客户类别实际上非常大。我必须为所有属性设置50个类。但对于较小的类来说,这确实是一个解决方案。谢谢你的帮助!:)我同意,在您的情况下,为此目的创建50个类是不值得的,但在每个类的逻辑都比您的复杂的情况下,有时创建大量小型类以利用多态性的能力是值得的。我也同意这一点。:)这个答案对未来的项目非常有帮助!