使用 FastMember 递归复制属性
Copy properties recursively with FastMember
我有两个来自这个 class 的对象:
public class A
{
public int Id { get; set; }
public string Name { get; set; }
public IList<B> Bs { get; set; }
}
public class B
{
public string Description { get; set; }
public IList<C> Cs { get; set; }
}
public class C
{
public string Description { get; set; }
}
现在我想用 FastMember 遍历两个对象实例的所有属性,并将属性从 object 1
复制到 object 2
。
这是我到目前为止得到的结果(没有用!)
// Set accessors
var sourceAccessor = ObjectAccessor.Create(object1);
var targetAccessor = ObjectAccessor.Create(object2);
foreach (var sourceItem in (IList)sourceAccessor.Target)
{
var targetItemAccessor = ObjectAccessor.Create(targetAccessor.Target);
var sourceItemAccessor = ObjectAccessor.Create(sourceItem);
// Overwrite property
targetItemAccessor[p] = sourceItemAccessor[p];
}
此代码显然不起作用...有什么想法吗?谢谢!
您可以在 TypeAccessor
的帮助下创建一个 shallow copy,方法如下:
var sourceAccessor = ObjectAccessor.Create(object1);
var targetAccessor = ObjectAccessor.Create(object2);
var access = TypeAccessor.Create(typeof(A));
var members = access.GetMembers();
foreach (var member in members)
{
targetAccessor[member.Name] = sourceAccessor[member.Name];
}
查看 FastMember tests 的用法示例。
对于深拷贝,您可以检查 属性 名称或使用 property type to determine whether to apply a deep copy of lists 或者浅拷贝是否足够。
编辑:这是一个简化版本的示例,它递归地复制类型 IList
的属性(请参阅此 question 如何确定哪个 属性 是列表),假设源对象和目标对象的列表长度相同:
private static void MirrorObject(object object1, object object2)
{
var sourceAccessor = ObjectAccessor.Create(object1);
var targetAccessor = ObjectAccessor.Create(object2);
var access = TypeAccessor.Create(object1.GetType());
var members = access.GetMembers();
foreach (var member in members)
{
if (member.Type.IsGenericType && (member.Type.GetGenericTypeDefinition() == typeof(IList<>)))
{
var list1 = (IList)sourceAccessor[member.Name];
var list2 = (IList)targetAccessor[member.Name];
if (list1.Count != list2.Count)
{
throw new ArgumentException("Lists need to be of the same length.");
}
for (var i = 0; i < list1.Count; ++i)
{
MirrorObject(list1[i], list2[i]);
}
}
else
{
targetAccessor[member.Name] = sourceAccessor[member.Name];
}
}
}
我有两个来自这个 class 的对象:
public class A
{
public int Id { get; set; }
public string Name { get; set; }
public IList<B> Bs { get; set; }
}
public class B
{
public string Description { get; set; }
public IList<C> Cs { get; set; }
}
public class C
{
public string Description { get; set; }
}
现在我想用 FastMember 遍历两个对象实例的所有属性,并将属性从 object 1
复制到 object 2
。
这是我到目前为止得到的结果(没有用!)
// Set accessors
var sourceAccessor = ObjectAccessor.Create(object1);
var targetAccessor = ObjectAccessor.Create(object2);
foreach (var sourceItem in (IList)sourceAccessor.Target)
{
var targetItemAccessor = ObjectAccessor.Create(targetAccessor.Target);
var sourceItemAccessor = ObjectAccessor.Create(sourceItem);
// Overwrite property
targetItemAccessor[p] = sourceItemAccessor[p];
}
此代码显然不起作用...有什么想法吗?谢谢!
您可以在 TypeAccessor
的帮助下创建一个 shallow copy,方法如下:
var sourceAccessor = ObjectAccessor.Create(object1);
var targetAccessor = ObjectAccessor.Create(object2);
var access = TypeAccessor.Create(typeof(A));
var members = access.GetMembers();
foreach (var member in members)
{
targetAccessor[member.Name] = sourceAccessor[member.Name];
}
查看 FastMember tests 的用法示例。
对于深拷贝,您可以检查 属性 名称或使用 property type to determine whether to apply a deep copy of lists 或者浅拷贝是否足够。
编辑:这是一个简化版本的示例,它递归地复制类型 IList
的属性(请参阅此 question 如何确定哪个 属性 是列表),假设源对象和目标对象的列表长度相同:
private static void MirrorObject(object object1, object object2)
{
var sourceAccessor = ObjectAccessor.Create(object1);
var targetAccessor = ObjectAccessor.Create(object2);
var access = TypeAccessor.Create(object1.GetType());
var members = access.GetMembers();
foreach (var member in members)
{
if (member.Type.IsGenericType && (member.Type.GetGenericTypeDefinition() == typeof(IList<>)))
{
var list1 = (IList)sourceAccessor[member.Name];
var list2 = (IList)targetAccessor[member.Name];
if (list1.Count != list2.Count)
{
throw new ArgumentException("Lists need to be of the same length.");
}
for (var i = 0; i < list1.Count; ++i)
{
MirrorObject(list1[i], list2[i]);
}
}
else
{
targetAccessor[member.Name] = sourceAccessor[member.Name];
}
}
}