예제 #1
0
        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 }));
        }
예제 #2
0
        private static void EmitDeferredColumnAssignment(ILGenerator generator, short memberVariableIndex, MetaColumn member)
        {
            string memberName = member.GetMemberKey();

            Type linkedMemberType     = member.Accessor.Type;
            Type linkType             = typeof(ILink <>).MakeGenericType(linkedMemberType);
            Type linkSourceType       = typeof(Func <>).MakeGenericType(linkedMemberType);
            Type associatorLoaderType = typeof(IAssociationLoader <>).MakeGenericType(linkedMemberType);

            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 containsKeyLabel = 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(MetaColumn));
            generator.Emit(OpCodes.Ldarg_2);
            generator.Emit(OpCodes.Call, _associationLoaderScalarMethod.MakeGenericMethod(linkedMemberType));
            generator.Emit(OpCodes.Dup);
            generator.Emit(OpCodes.Ldvirtftn, associationLoadMethod);
            generator.Emit(OpCodes.Newobj, linkSourceConstructor);
            generator.Emit(OpCodes.Callvirt, linkSourceSetterMethod);
            generator.Emit(OpCodes.Ldarg_2);
            generator.Emit(OpCodes.Ldstr, memberName);
            generator.Emit(OpCodes.Call, _valueSetContainsKeyMethod);
            generator.Emit(OpCodes.Brfalse, containsKeyLabel);
            generator.Emit(OpCodes.Ldloc, variableIndex);

            if (member.Binder != null)
            {
                generator.Emit(OpCodes.Ldloc, memberVariableIndex);
                generator.Emit(OpCodes.Castclass, typeof(MetaColumn));
                generator.Emit(OpCodes.Callvirt, _metaColumnGetBinderMethod);
            }

            generator.Emit(OpCodes.Ldarg_2);
            generator.Emit(OpCodes.Ldstr, memberName);

            if (member.Binder != null)
            {
                generator.Emit(OpCodes.Call, _valueSetGetItemMethod.MakeGenericMethod(typeof(object)));
                generator.Emit(OpCodes.Callvirt, _columnBinderToPropertyValueMethod);

                if (member.Type.IsValueType)
                {
                    generator.Emit(OpCodes.Unbox_Any, linkedMemberType);
                }
                else
                {
                    generator.Emit(OpCodes.Castclass, linkedMemberType);
                }
            }
            else
            {
                generator.Emit(OpCodes.Call, _valueSetGetItemMethod.MakeGenericMethod(linkedMemberType));
            }

            generator.Emit(OpCodes.Callvirt, linkValueSetterMethod);

            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);
        }
예제 #3
0
        private static void EmitColumnAssignment(ILGenerator generator, short memberVariableIndex, MetaColumn member)
        {
            string memberName = member.GetMemberKey();

            Label containsKeyLabel = generator.DefineLabel();

            generator.Emit(OpCodes.Ldarg_2);
            generator.Emit(OpCodes.Ldstr, memberName);
            generator.Emit(OpCodes.Call, _valueSetContainsKeyMethod);
            generator.Emit(OpCodes.Brfalse, containsKeyLabel);

            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);

            if (member.Binder != null)
            {
                generator.Emit(OpCodes.Ldloc, memberVariableIndex);
                generator.Emit(OpCodes.Castclass, typeof(MetaColumn));
                generator.Emit(OpCodes.Callvirt, _metaColumnGetBinderMethod);
            }

            generator.Emit(OpCodes.Ldarg_2);
            generator.Emit(OpCodes.Ldstr, memberName);

            if (member.Binder != null)
            {
                generator.Emit(OpCodes.Call, _valueSetGetItemMethod.MakeGenericMethod(typeof(object)));
                generator.Emit(OpCodes.Callvirt, _columnBinderToPropertyValueMethod);
            }
            else
            {
                generator.Emit(OpCodes.Call, _valueSetGetItemMethod.MakeGenericMethod(member.Type));
                if (member.Type.IsValueType)
                {
                    generator.Emit(OpCodes.Box, member.Type);
                }
            }

            generator.Emit(OpCodes.Callvirt, _metaAccessorSetValueMethod);
            generator.MarkLabel(containsKeyLabel);
        }