void CreateSaverIl(IILGen ilGen, IEnumerable <TableFieldInfo> fields, Action <IILGen> pushInstance, Action <IILGen> pushRelationIface, Action <IILGen> pushWriter, Action <IILGen> pushTransaction) { var anyNeedsCtx = fields.Any(tfi => tfi.Handler.NeedsCtx()); IILLocal writerCtxLocal = null; if (anyNeedsCtx) { writerCtxLocal = ilGen.DeclareLocal(typeof(IWriterCtx)); ilGen .Do(pushTransaction) .Do(pushWriter) .Newobj(() => new DBWriterCtx(null, null)) .Stloc(writerCtxLocal); } var props = ClientType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (var field in fields) { var getter = props.First(p => GetPersistentName(p) == field.Name).GetGetMethod(true); Action <IILGen> writerOrCtx; var handler = field.Handler.SpecializeSaveForType(getter.ReturnType); if (handler.NeedsCtx()) { writerOrCtx = il => il.Ldloc(writerCtxLocal); } else { writerOrCtx = pushWriter; } MethodInfo apartFieldGetter = null; if (pushRelationIface != null) { ApartFields.TryGetValue(field.Name, out apartFieldGetter); } handler.Save(ilGen, writerOrCtx, il => { if (apartFieldGetter != null) { il.Do(pushRelationIface); getter = apartFieldGetter; } else { il.Do(pushInstance); } il.Callvirt(getter); _relationInfoResolver.TypeConvertorGenerator.GenerateConversion(getter.ReturnType, handler.HandledType())(il); }); } }
Action <IInternalObjectDBTransaction, AbstractBufferedWriter, object, object> CreateSaverWithApartFields( IEnumerable <TableFieldInfo> fields, string saverName) { var method = ILBuilder.Instance.NewMethod < Action <IInternalObjectDBTransaction, AbstractBufferedWriter, object, object> >(saverName); var ilGenerator = method.Generator; ilGenerator.DeclareLocal(ClientType); StoreNthArgumentOfTypeIntoLoc(ilGenerator, 2, ClientType, 0); var hasApartFields = ApartFields.Any(); if (hasApartFields) { ilGenerator.DeclareLocal(_interfaceType); StoreNthArgumentOfTypeIntoLoc(ilGenerator, 3, _interfaceType, 1); } CreateSaverIl(ilGenerator, fields, il => il.Ldloc(0), hasApartFields ? il => il.Ldloc(1) : (Action <IILGen>)null, il => il.Ldarg(1), il => il.Ldarg(0)); ilGenerator .Ret(); return(method.Create()); }