如何将可变长度列表映射到对象属性?
问题描述:
在这种情况下我有一个包含与此命名约定一些字符串属性的对象Foo
:Foo.Bar1
,Foo.Bar2
,等...如何将可变长度列表映射到对象属性?
我想用未知长度的字符串列表来映射到每个Bar
( N)属性:
public class Mapper()
{
public Foo MapToFoo(List<string> list)
{
var Foo = new Foo();
foreach (var item in list)
{
//? Here is some psudo-code/logic of what I am trying to achieve:
//Bar*X* = item
//X++
}
return Foo;
}
}
public class Foo
{
public string Bar1 { get; set; }
public string Bar2 { get; set; }
public string Bar3 { get; set; }
}
我承认我可以只添加public List<string> Bars
和摆脱Bar1
,Bar2
,Bar3
。虽然这可能是首选的解决方案,但在我的特殊情况下,需要对紧密结合的传统项目进行大量更改。
有没有办法做到这一点?如果是这样,那么映射永远不会寻找不存在的BarX(即在这种情况下为Bar4
)?
答
既然你不能使用像Bars
任何东西,你可能需要使用反射,这样的事情:
public class Mapper
{
public Foo MapToFoo(List<string> list)
{
var Foo = new Foo();
var props = typeof(Foo).GetProperties()
.Where(pi => pi.Name.StartsWith("Bar"))
.OrderBy(pi => pi.Name).ToList();
for (int i = 0; i < Math.Min(list.Count, props.Count); i++)
props[i].SetValue(Foo, list[i]);
return Foo;
}
}
但也许使用属性名称的Dictionary<string, string>
和值更适合:
var mapper = new Mapper();
var values = new Dictionary<string, String>();
values["Bar1"] = "A";
values["Bar2"] = "B";
values["Bar3"] = "C";
var foo = mapper.MapToFoo(values);
...
public class Mapper
{
public Foo MapToFoo(Dictionary<string, string> values)
{
var Foo = new Foo();
foreach (var item in values)
{
var prop = typeof(Foo).GetProperty(item.Key);
if (prop != null)
prop.SetValue(Foo, item.Value);
}
return Foo;
}
}
答
您可以使用反射来实现相同。假设你的属性被命名为Bar1,Bar2,Bar3 ...等等,你可以执行以下操作。
public Foo MapToFoo(List<string> list)
{
var Foo = new Foo();
var propertyName = "Bar";
int index = 1;
foreach (var item in list)
{
var property = Foo.GetType().GetProperty(string.Format("{0}{1}", propertyName, index));
if(property != null)
{
property.SetValue(Foo, item);
}
index++;
}
return Foo;
}
答
我的意思是,你可以使用反射得到所有的属性:
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
//Store the values in an sort them
}
但这不保证顺序,这样你将不得不对它们进行排序。
只因为你可以,并不意味着你应该。你应该问自己:“我为什么要这样做?”和“是否有更简单/更易维护的解决方案?”
答
您可以使用反射:
public class Mapper()
{
public Foo MapToFoo(List<string> list)
{
Foo f = new Foo();
var bars = f.GetType().GetProperties();
int i=0;
foreach (var item in list)
{
bars[i++].SetValue(f, item);
if(i==bars.Length)
break;
}
return f;
}
}
public class Foo
{
public string Bar1 { get; set; }
public string Bar2 { get; set; }
public string Bar3 { get; set; }
}
这是可能的,你将有你有许多悬而未决的要求,才能使用云南财贸为 –
。如果列表的字符串多于Foo的属性,该怎么办?如果有更多的Foo属性比字符串?反射的属性不保证顺序,字符串2可以设置Bar3值吗?我建议你不要这样做,建立一个[Adapter](https://en.wikipedia.org/wiki/Adapter_pattern)来桥接遗留代码。 – Crowcoder