2013-04-10 2 views
3

Я смотрю на превосходную микро-Orm Dapper, а в проекте Dapper.Rainbow есть код, который создает таблицу ctor, используя IL. Я надеялся, что кто-то может объяснить мне, что делает этот код - очевидно, что это динамически испускающий код для создания конструктора (или это код для вызова конструктора или того и другого), но каков код, который испускается фактически, и почему это необходимо?Почему Dapper испускает IL-код в CreateTableConstructor?

Вот код

protected Action<TDatabase> CreateTableConstructor(Type tableType) 
{ 
    var dm = new DynamicMethod("ConstructInstances", null, new Type[] { typeof(TDatabase) }, true); 
    var il = dm.GetILGenerator(); 

    var setters = GetType().GetProperties() 
     .Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == tableType) 
     .Select(p => Tuple.Create(
       p.GetSetMethod(true), 
       p.PropertyType.GetConstructor(new Type[] { typeof(TDatabase), typeof(string) }), 
       p.Name, 
       p.DeclaringType 
     )); 

    foreach (var setter in setters) 
    { 
     il.Emit(OpCodes.Ldarg_0); 
     // [db] 

     il.Emit(OpCodes.Ldstr, setter.Item3); 
     // [db, likelyname] 

     il.Emit(OpCodes.Newobj, setter.Item2); 
     // [table] 

     var table = il.DeclareLocal(setter.Item2.DeclaringType); 
     il.Emit(OpCodes.Stloc, table); 
     // [] 

     il.Emit(OpCodes.Ldarg_0); 
     // [db] 

     il.Emit(OpCodes.Castclass, setter.Item4); 
     // [db cast to container] 

     il.Emit(OpCodes.Ldloc, table); 
     // [db cast to container, table] 

     il.Emit(OpCodes.Callvirt, setter.Item1); 
     // [] 
    } 

    il.Emit(OpCodes.Ret); 
    return (Action<TDatabase>)dm.CreateDelegate(typeof(Action<TDatabase>)); 
} 
+0

Хотя я не участвую в проекте ct, похоже, он создает конструктор, в котором он может устанавливать значения модели непосредственно из модели базы данных. Это просто код котельной плиты. –

+0

Спасибо за комментарий и изменения. Итак, каков эквивалент C# этого кода IL ctor - и делает ли это это, чтобы избавить меня от необходимости добавлять эти ctors ко всем моим классам моделей? –

ответ

3

В основном, она принимает все свойства текущего типа (который является производным от Database<T>), которые выглядят примерно так:

public Table<SomeEntity> SomeTable { get; private set; } 

И создает делегат, который выполняет для каждого такого имущества:

var table = new Table<SomeEntity>(db, "SomeTable"); 
db.SomeTable = table; 
Смежные вопросы