public static IAssociationLoader <TAssociation> Single <TAssociation>(MetaAssociation association, IValueSet source) { // Gonna move to DbQueryGenerator MetaType otherType = Configuration.Instance.Factory.CreateMapping(typeof(TAssociation)); StringBuilder builder = new StringBuilder(); builder.Append("SELECT "); foreach (MetaMember member in otherType.Members) { builder.Append('[').Append(member.GetMemberKey()).Append("],"); } builder.Length--; builder.Append(" FROM "); if (!String.IsNullOrEmpty(otherType.Schema)) { builder.Append('[').Append(otherType.Schema).Append("]."); } builder.Append('[').Append(otherType.Table).Append("] WHERE [") .Append(association.OtherKey).Append("]=@").Append(association.OtherKey); ValueDictionary arguments = new ValueDictionary(); arguments.Add(association.OtherKey, source.GetValue <object>(association.ThisKey)); return(new SingleMappedAssociationLoader <TAssociation>(new DbCommandDescriptor(builder.ToString(), arguments))); }
public static IDbSerializer Build(MetaType type) { Type entityType = type.Type; // first build the deserializer method DynamicMethod method = new DynamicMethod("Deserialize", entityType, new Type[] { typeof(MetaType), entityType, typeof(IDbValueSet) }, entityType, true); ILGenerator generator = method.GetILGenerator(); short memberVariableIndex = (short)generator.DeclareLocal(typeof(MetaMember)).LocalIndex; foreach (MetaMember member in type.Members) { if (member.IsAssociation) { MetaAssociation association = (MetaAssociation)member; if (association.Accessor.IsDeferred) { EmitDeferredAssociationAssignment(generator, memberVariableIndex, association); } } else { MetaColumn column = (MetaColumn)member; if (column.Accessor.IsDeferred) { EmitDeferredColumnAssignment(generator, memberVariableIndex, column); } else { EmitColumnAssignment(generator, memberVariableIndex, column); } } } generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Ret); Type serializerType = typeof(DelegatedDbSerializer <>).MakeGenericType(entityType); object deserializer = method.CreateDelegate(typeof(Func <, , ,>).MakeGenericType( typeof(MetaType), entityType, typeof(IDbValueSet), entityType)); return((IDbSerializer)Activator.CreateInstance(serializerType, new object[] { type, null, deserializer })); }
private static void EmitDeferredAssociationAssignment(ILGenerator generator, short memberVariableIndex, MetaAssociation member) { string memberName = member.GetMemberKey(); Type linkedMemberType = member.Accessor.Type; Type linkedElementType = linkedMemberType.GetSequenceElementType(); Type linkType = typeof(ILink <>).MakeGenericType(linkedMemberType); Type linkSourceType = typeof(Func <>).MakeGenericType(linkedMemberType); Type associatorLoaderType = typeof(IAssociationLoader <>).MakeGenericType(linkedMemberType); MethodInfo associatorFactoryMethod = (member.IsMany) ? _associationLoaderMultipleMethod.MakeGenericMethod(linkedElementType) : _associationLoaderSingleMethod.MakeGenericMethod(linkedElementType); MethodInfo associationLoadMethod = associatorLoaderType.GetMethod("Load"); MethodInfo linkSourceSetterMethod = linkType.GetProperty("Source").GetSetMethod(); MethodInfo linkValueSetterMethod = linkType.GetProperty("Value").GetSetMethod(); ConstructorInfo typeConstructor = member.Type.GetConstructor(Type.EmptyTypes); ConstructorInfo linkSourceConstructor = linkSourceType.GetConstructor(new Type[] { typeof(object), typeof(IntPtr) }); short variableIndex = (short)generator.DeclareLocal(linkType).LocalIndex; Label linkIsNullLabel = generator.DefineLabel(); Label skipLabel = generator.DefineLabel(); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Callvirt, _metaTypeGetMembersMethod); generator.Emit(OpCodes.Ldstr, memberName); generator.Emit(OpCodes.Callvirt, _metaTypeGetMemberMethod); generator.Emit(OpCodes.Stloc, memberVariableIndex); generator.Emit(OpCodes.Ldloc, memberVariableIndex); generator.Emit(OpCodes.Callvirt, _metaMemberGetAccessorMethod); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Callvirt, _metaAccessorGetValueMethod); generator.Emit(OpCodes.Castclass, linkType); generator.Emit(OpCodes.Stloc, variableIndex); generator.Emit(OpCodes.Ldloc, variableIndex); if (typeConstructor == null) { generator.Emit(OpCodes.Brtrue, skipLabel); } else { generator.Emit(OpCodes.Brtrue, linkIsNullLabel); } generator.Emit(OpCodes.Newobj, typeConstructor); generator.Emit(OpCodes.Stloc, variableIndex); generator.MarkLabel(linkIsNullLabel); generator.Emit(OpCodes.Ldloc, variableIndex); generator.Emit(OpCodes.Ldloc, memberVariableIndex); generator.Emit(OpCodes.Castclass, typeof(MetaAssociation)); generator.Emit(OpCodes.Ldarg_2); generator.Emit(OpCodes.Call, associatorFactoryMethod); generator.Emit(OpCodes.Dup); generator.Emit(OpCodes.Ldvirtftn, associationLoadMethod); generator.Emit(OpCodes.Newobj, linkSourceConstructor); generator.Emit(OpCodes.Callvirt, linkSourceSetterMethod); // here we attempt to decode and write a value. //generator.MarkLabel(containsKeyLabel); generator.Emit(OpCodes.Ldloc, memberVariableIndex); generator.Emit(OpCodes.Callvirt, _metaMemberGetAccessorMethod); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Ldloc, variableIndex); generator.Emit(OpCodes.Callvirt, _metaAccessorSetValueMethod); generator.MarkLabel(skipLabel); }