Nesnenin özelliklerini yansıma kullanmadan DynamicBuilder on CodeProject benzeri bir şekilde doldurmak istiyorum. CodeProject örneği, bir DataReader veya DataRecord kullanarak varlıkların doldurulması için uyarlanmıştır. Bunu iyi etki için birkaç DAL'de kullanıyorum. Şimdi bir sözlük veya başka bir veri agnostik nesneyi kullanmak için değiştirmek istiyorum, böylece ben DAL kodda kullanamıyorum - şu anda yansıma kullandığım yerler. OpCodes ve IL hakkında neredeyse hiçbir şey bilmiyorum. Sadece iyi çalıştığını ve yansımadan daha hızlı olduğunu biliyorum.Dinamik nesne özellik popülatörü (yansıma olmadan)
CodeProject örneğini değiştirmeye çalıştım ve IL ile ilgili bilgisizliğim nedeniyle, iki satırda sıkışmış durumdayım. Bunlardan
- Bir DBNULLs ilgilenir ve ben sadece onu kaybedebilir eminim, ama hatları önceki ve onu ilişkilidir ve gitmek için de bunlardan hangisinin gereken aşağıdaki eğer bilmiyorum.
- Diğeri, daha önce veri kaydının değerini çeken ve şimdi onu sözlükten çıkarmak zorunda olan bence. Sanırım "getValueMethod" özelliğini "property.Value" ile değiştirebiliyorum ama emin değilim.
Bu kediyi de cildin alternatif/daha iyi yollarına açığım.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
public class Populator<T>
{
private delegate T Load(Dictionary<string, object> properties);
private Load _handler;
private Populator() { }
public T Build(Dictionary<string, object> properties)
{
return _handler(properties);
}
public static Populator<T> CreateBuilder(Dictionary<string, object> properties)
{
//private static readonly MethodInfo getValueMethod = typeof(IDataRecord).GetMethod("get_Item", new [] { typeof(int) });
//private static readonly MethodInfo isDBNullMethod = typeof(IDataRecord).GetMethod("IsDBNull", new [] { typeof(int) });
Populator<T> dynamicBuilder = new Populator<T>();
DynamicMethod method = new DynamicMethod("Create", typeof(T), new[] { typeof(Dictionary<string, object>) }, typeof(T), true);
ILGenerator generator = method.GetILGenerator();
LocalBuilder result = generator.DeclareLocal(typeof(T));
generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes));
generator.Emit(OpCodes.Stloc, result);
int i = 0;
foreach (var property in properties)
{
PropertyInfo propertyInfo = typeof(T).GetProperty(property.Key, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy | BindingFlags.Default);
Label endIfLabel = generator.DefineLabel();
if (propertyInfo != null && propertyInfo.GetSetMethod() != null)
{
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldc_I4, i);
//generator.Emit(OpCodes.Callvirt, isDBNullMethod);
generator.Emit(OpCodes.Brtrue, endIfLabel);
generator.Emit(OpCodes.Ldloc, result);
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldc_I4, i);
//generator.Emit(OpCodes.Callvirt, getValueMethod);
generator.Emit(OpCodes.Unbox_Any, property.Value.GetType());
generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod());
generator.MarkLabel(endIfLabel);
}
i++;
}
generator.Emit(OpCodes.Ldloc, result);
generator.Emit(OpCodes.Ret);
dynamicBuilder._handler = (Load)method.CreateDelegate(typeof(Load));
return dynamicBuilder;
}
}
DÜZENLEME: kod (HyperDescriptor ile) Marc Gravell en PropertyDescriptor uygulanmasını kullanma
basitleştirilmiş İşte
bugüne kadar kod (yorumlandı hatlar ı şaşırıp olanlar) yüz kat. Şimdi aşağıdaki test var: Her iki TypeDescriptor.GetProperties için performans değerlendirmeleri esasusing System;
using System.Collections.Generic;
using System.ComponentModel;
using Hyper.ComponentModel;
namespace Test
{
class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
class Program
{
static void Main()
{
HyperTypeDescriptionProvider.Add(typeof(Person));
var properties = new Dictionary<string, object> { { "Id", 10 }, { "Name", "Fred Flintstone" } };
Person person = new Person();
DynamicUpdate(person, properties);
Console.WriteLine("Id: {0}; Name: {1}", person.Id, person.Name);
Console.ReadKey();
}
public static void DynamicUpdate<T>(T entity, Dictionary<string, object> properties)
{
foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(typeof(T)))
if (properties.ContainsKey(propertyDescriptor.Name))
propertyDescriptor.SetValue(entity, properties[propertyDescriptor.Name]);
}
}
}
herhangi bir yorum() & PropertyDescriptor.SetValue() bekliyoruz ...
(yorum yapmak cevap) –