我创建了一个(动态生成的类型)集合,用于在silverlight网格中显示,其中一个过程涉及创建导入(动态生成的类型)类型,然后将导入类型的属性映射到(动态生成的类型)的集合)两种类型共享标识项目的Id属性(无论是在网格上还是在导入中)
即 绑定到网格的类型
int Id {get; set}
string Foo {get;set;}
string FooFoo {get;set;}
并导入类型
int Id {get; set}
string Foo {get;set}
其中id匹配我想复制foos。
在集合中将属性从一种类型映射到另一种类型的快速方法是什么?
修改
感谢Stephan的最终Typemapper实现,因为一个功能只会在keymembers相等时映射两种类型,通过代表成员名称的字典字符串字符串定义映射,在silverlight中工作
public class TypeMapper
{
private readonly DynamicMethod _mapper;
public static DynamicMethod BuildMapper(Type fromType,
Type toType,
KeyValuePair<string, string> keyMemberMap,
Dictionary<string, string> memberMappings)
{
var method = new DynamicMethod("Map", typeof(bool), new[] { fromType, toType });
// Preparing Reflection instances
MethodInfo getFromKeyMethod = fromType.GetMethod(
string.Format("get_{0}", keyMemberMap.Key),
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
MethodInfo getToKeyMethod = toType.GetMethod(
string.Format("get_{0}", keyMemberMap.Value),
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
ILGenerator gen = method.GetILGenerator();
// Preparing locals
gen.DeclareLocal(typeof(Boolean));
// Preparing labels
Label labelNoMatch = gen.DefineLabel();
// Writing body
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Callvirt, getFromKeyMethod);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Callvirt, getToKeyMethod);
gen.Emit(OpCodes.Ceq);
gen.Emit(OpCodes.Stloc_0);
gen.Emit(OpCodes.Ldloc_0);
gen.Emit(OpCodes.Brfalse_S, labelNoMatch);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Ldarg_0);
foreach (var mapping in memberMappings)
{
var getFromValueMethod = fromType.GetMethod(
string.Format("get_{0}", mapping.Key),
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
var setToValueMethod = toType.GetMethod(
string.Format("set_{0}", mapping.Value),
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
gen.Emit(OpCodes.Callvirt, getFromValueMethod);
gen.Emit(OpCodes.Callvirt, setToValueMethod);
}
gen.MarkLabel(labelNoMatch);
gen.Emit(OpCodes.Ldloc_0);
gen.Emit(OpCodes.Ret);
return method;
}
public void Map (object fromInstance, object toInstance)
{
_mapper.Invoke(null, new[] { fromInstance, toInstance });
}
public TypeMapper(Type fromType, Type toType,
KeyValuePair<string, string> keyMemberMap,
Dictionary<string, string> memberMappings)
{
_mapper = BuildMapper(fromType, toType, keyMemberMap, memberMappings);
}
}
答案 0 :(得分:1)
bound.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList()
.ForEach(s =>
{
var prop = import.GetType().GetProperty(s.Name,BindingFlags.Public | BindingFlags.Instance);
if(prop != null)
{
prop.SetValue(import,s.GetValue(bound,null),null);
}
});
这会将属性从一个项目映射到另一个项目。如果您想在集合中执行此操作,请创建一个方法并执行myCollection.Select(o => MapProperties(o,mapType));
。
注意:该方法当前使用现有对象并复制到其中。您可以使用除类型之外的方法,然后调用Activator.CreateInstance(type)
并将其设置为我的代码段的导入值。
修改强>
本文提供了一个很好的示例,可以生成DynamicMethod
来执行动态对象的深层复制。它将比反射解决方案具有更长的设置时间,但每次后续调用都将与编译时一样快。
修改强>
实际例子:
DynamicMethod GetMapper(Type type1, Type type2)
{
DynamicMethod method = new DynamicMethod("junk", type2,
new Type[] { type1 });
ILGenerator il = method.GetILGenerator();
LocalBuilder obj0 = il.DeclareLocal(type2); //target
// create object and store in local 0
ConstructorInfo ctor = type2.GetConstructor(
new Type[] { });
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Stloc_0);
PropertyInfo[] properties = type1.GetProperties(BindingFlags.Instance
| BindingFlags.Public | BindingFlags.FlattenHierarchy);
foreach (PropertyInfo prop in properties)
{
// local constructed object
il.Emit(OpCodes.Ldloc_0);
// load source argument
il.Emit(OpCodes.Ldarg_0);
// get property value
il.EmitCall(OpCodes.Callvirt, type1.GetMethod(
"get_" + prop.Name), null);
il.EmitCall(OpCodes.Callvirt, type2.GetMethod(
"set_" + prop.Name), null);
}
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);
return method;
}
您应该能够GetMapper(sourceType,destinationType).Invoke(null,new [] { myObject});