我正在尝试编写一些有效的C#代码,以根据成员名称列表将选定的类成员从对象A复制到对象B。所讨论的类将具有字符串成员和类成员的组合。这是类布局的示例。
public class Class0
{
public string C0Prop1 { get; set; } = "c0.prop1";
}
public class Class1
{
public string C1Prop1 { get; set; } = "c1.prop1";
public string C1Prop2 { get; set; } = "c1.prop2";
}
public class Class2
{
public string C2Prop1 { get; set; } = "c2.prop1";
public Class1 C2Prop2 { get; set; } = new Class1();
public string C2Prop3 { get; set; } = "c2.prop3";
public string C2Prop4 { get; set; } = "c2.prop4";
public Class0 C2Prop5 { get; set; } = new Class0();
}
然后我有一个函数foo(),它具有一个列表'props',该列表是Class2某些成员的名称。
我的目标是提供一些紧凑的代码,使我可以仅将C2Prop2和C2Prop4从源对象复制到目标对象。最终,“ props”被传递到foo()中,因此它将是动态的,并且foo()可以复制任何元素。
foo()
{
BindingFlags _flags = BindingFlags.GetProperty | BindingFlags.IgnoreCase |
BindingFlags.Instance | BindingFlags.Static |
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.FlattenHierarchy;
Class2 source = new Class2();
Class2 dest = new Class2();
List<string> props = new List<string>() { nameof(Class2.C2Prop2), nameof(Class2.C2Prop4) };
foreach (string prop in props)
{
var s = source.GetType().GetProperty(prop, _flags).GetValue(source, null);
if (s != null)
{
if (String.Compare(prop, nameof(Class2.C2Prop2), true) == 0)
{ // one option could be json
dest.C2Prop2 = JsonConvert.DeserializeObject<Class2>(JsonConvert.SerializeObject(s));
}
else
if (String.Compare(prop, nameof(Class2.C2Prop5), true) == 0)
{ // another option for copy
dest.C2Prop5 = source.C2Prop5;
}
else
{ // this is a simple string member, just assign it.
dest.GetType().GetProperty(prop, _flags).SetValue(dest, s.ToString());
}
}
}
}
在此示例中,我遍历“ props”列表,并使用PropertyInfo确定源成员的特征,然后确定它是类还是字符串,并相应地进行复制。我确信必须有一种最佳的方法来将类对象的单个成员从源复制到目标,但是就我的生活而言,我还不太清楚。
在此方面的任何帮助将不胜感激!
答案 0 :(得分:0)
我能够为源对象和目标对象利用PropertyInfo的GetSetMethod()和GetGetMethod()来执行通用副本。前提是假定成员将需要具有公共获取者和设置者,但是这种逻辑使我可以最大程度地减少代码量。
随时推荐改进之处。
public void copyAttrs(List<string> props, ref Class2 source, ref Class2 dest)
{
BindingFlags _flags = BindingFlags.GetProperty | BindingFlags.IgnoreCase |
BindingFlags.Instance | BindingFlags.Static |
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.FlattenHierarchy;
foreach (string prop in props)
{
var propSource = source.GetType().GetProperty(prop, _flags);
var proDest = dest.GetType().GetProperty(prop,_flags);
if ((propDest != null) && (propSource != null))
{
MethodInfo destSetMethod = propDest.GetSetMethod();
MethodInfo sourceGetMethod = propSource.GetGetMethod();
if ((destSetMethod != null) && (sourceGetMethod != null))
destSetMethod.Invoke(dest, new object[] { sourceGetMethod.Invoke(source, null) });
}
}
}