Im создание коллекции (динамически сгенерированного типа) для отображения в сетке silverlight и один из процессов включает создание типа импорта (динамически сгенерированного типа), а затем сопоставление свойств по типу импорта сбор (динамически типа) оба типа обладают свойством Id, который идентифицирует элемент (будь то на сетке или в импорте)Сопоставление объектов с объектами в коллекциях
т.е. типа, связанного с сеткой
int Id {get; set}
string Foo {get;set;}
string FooFoo {get;set;}
и импортировать тип
int Id {get; set}
string Foo {get;set}
где идентификаторы совпадают, я хочу скопировать foos.
Что такое быстрый способ сопоставления свойств одного типа другому в коллекции?
EDIT
Heres окончательная реализация Typemapper с благодарностью Stephan, как функция будет отображать только два типа, когда keymembers равны, отображение, определенное с помощью словаря строки строки, представляющего имена элементов, произведения in 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);
}
}
я сделал нечто подобное, оказывается медленным (с помощью отражения), когда мы учитывая несколько тысяч. все еще +1 –
Если типы динамически генерируются, это, скорее всего, лучшее, что вы собираетесь делать. Вы можете немного ускорить его, используя 'Reflection.Emit', чтобы сгенерировать делегат фабрики, а затем запустить его, но я не уверен, какой именно путь это сделать. Вы можете взглянуть на MSDN для 'Reflection.Emit', поскольку это может дать хорошее направление. – Stephan
Забыл, что это вопрос Silverlight. Мое второе решение, вероятно, не будет работать для Silverlight. Это можно было бы сделать как операцию на стороне сервера (например, с RIA), но, как чисто клиентская сторона, скорее всего, это не сработает. – Stephan