public static void Generate(TypeBuilder typeBuilder, 
            TypeMetadata metadata, 
            FieldMetadataFieldBuilderMap fieldMetadataFieldBuilderMap)
        {
            var constructorCount = metadata.Constructors.Length;

            for (var i = 0; i < constructorCount; i++)
            {
                var constructor = metadata.Constructors[i];

                GenerateConstructor(typeBuilder, metadata, constructor, fieldMetadataFieldBuilderMap);
            }
        }
        public static FieldMetadataFieldBuilderMap Generate(TypeBuilder typeBuilder, TypeMetadata typeMetadata)
        {
            var fieldCount = typeMetadata.Fields.Length;

            var fieldMap = new FieldMetadataFieldBuilderMap(fieldCount);

            for (var i = 0; i < fieldCount; i++)
            {
                var fieldMetadata = typeMetadata.Fields[i];

                var field = GenerateField(typeBuilder, fieldMetadata);

                fieldMap.Add(fieldMetadata, field);
            }

            return fieldMap;
        }
        public static MethodMetadataFieldBuilderMap Generate(TypeBuilder typeBuilder, TypeMetadata metadata)
        {
            var methodCount = metadata.Methods.Length;

            var methodMetadataFields = new MethodMetadataFieldBuilderMap(methodCount);

            for (var i = 0; i < methodCount; i++)
            {
                var method = metadata.Methods[i];
                var metadataField = method.MetadataField;

                var field = typeBuilder.DefineField(
                    metadataField.Name,
                    metadataField.FieldType,
                    Type.EmptyTypes,
                    Type.EmptyTypes,
                    metadataField.FieldAttributes);

                methodMetadataFields.Add(method, field);
            }

            return methodMetadataFields;
        }
        private static void GenerateConstructor(
            TypeBuilder typeBuilder, 
            TypeMetadata typeMetadata,
            ConstructorMetadata constructorMetadata,
            FieldMetadataFieldBuilderMap fieldBuilders)
        {
            var constructor = typeBuilder.DefineConstructor(
                constructorMetadata.MethodAttributes,
                CallingConventions.Standard,
                constructorMetadata.ParameterTypes);

            DefineParameterNames(constructor, constructorMetadata);

            var il = constructor.GetILGenerator();

            InitializeInstanceFields(il, typeMetadata, constructorMetadata, fieldBuilders);

            if (constructorMetadata.CallBaseConstructor)
            {
                GenerateBaseConstructorCall(il, constructorMetadata);
            }

            il.Emit(OpCodes.Ret);
        }
        private static void InitializeInstanceFields(
            ILGenerator il, 
            TypeMetadata typeMetadata,
            ConstructorMetadata constructorMetadata,
            FieldMetadataFieldBuilderMap fieldBuilders)
        {
            for (var i = 0; i < constructorMetadata.Parameters.Length; i++)
            {
                var parameter = constructorMetadata.Parameters[i];

                var dispatcherParameter = parameter as ConstructorDispatcherParameterMetadata;
                var targetParameter = parameter as ConstructorTargetParameterMetadata;

                if (dispatcherParameter != null)
                {
                    InitializeField(il, dispatcherParameter.InstanceField, dispatcherParameter, fieldBuilders);
                }
                else if(targetParameter != null)
                {
                    InitializeField(il, targetParameter.InstanceField, targetParameter, fieldBuilders);
                }
            }

            for (var i = 0; i < typeMetadata.Targets.Length; i++)
            {
                var target = typeMetadata.Targets[i];

                if (target.IsProxyInstantiated)
                {
                    InitializeTarget(il, target.InstanceField, target.TargetType, fieldBuilders);
                }
            }
        }