protected void GenerateInitInstanceIL(Dictionary<TypeFactoryDefinition, LocalBuilder> sharedVars,
            Dictionary<TypeFactoryMap, FieldBuilder> singletonVars,
            TypeFactoryDefinition definition,
            ILGenerator il)
        {
            foreach (var constMap in definition.ParameterTypeMaps)
            {
                var constDef = constMap.Definition;
                if (constDef.IsShared)
                {
                    var local = sharedVars[constDef];
                    il.Emit(OpCodes.Ldloc, local);
                    continue;
                }
                if (constDef.IsSingleton)
                {
                    var field = singletonVars[constMap];
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldfld, field);
                    il.Emit(OpCodes.Callvirt, field.FieldType.GetMethod("GetValueAs").MakeGenericMethod(constMap.BaseType));
                    continue;
                }

                GenerateInitInstanceIL(sharedVars, singletonVars, constDef, il);
            }

            if (definition.IsFactoryMethod)
                il.Emit(OpCodes.Call, definition.FactoryMethodInfo);
            else
                il.Emit(OpCodes.Newobj, definition.ConstructorInfo);
        }
        public TypeFactoryGenerator(TypeFactoryDefinition definition)
        {
            var typeSuffix = (definition.IsFactoryMethod ? "FactoryMethod_" + definition.MappedType.Name + "_" + definition.FactoryMethodInfo.Name : definition.MappedType.Name);
            this.loaderBuilder = DynamicAssemblyManager.DefineType("LoaderFor" + typeSuffix);
            this.factoryBuilder = DynamicAssemblyManager.DefineType("FactoryFor" + typeSuffix);
            this.definition = definition;

            GenerateTypes();
        }
        public TypeFactoryDefinition GetTypeFactoryDefinition(TypeFactoryMap map, Stack<TypeFactoryMap> current)
        {
            var definition = new TypeFactoryDefinition(map, current);
            TypeFactoryDefinition result = null;

            if (!typeFactoryDefinitions.TryGetValue(definition, out result))
            {
                lock (syncLock)
                {
                    if (!typeFactoryDefinitions.TryGetValue(definition, out result))
                    {
                        typeFactoryDefinitions.Add(definition, definition);
                        result = definition;
                    }
                }
            }

            return result;
        }
 protected void InitSharedVarsOnParameters(Dictionary<TypeFactoryDefinition, LocalBuilder> sharedVars, TypeFactoryDefinition def, ILGenerator il)
 {
     foreach (var parameterMap in def.ParameterTypeMaps)
     {
         InitSharedVars(sharedVars, parameterMap.Definition, il);
     }
 }
        protected void InitSharedVars(Dictionary<TypeFactoryDefinition, LocalBuilder> sharedVars, TypeFactoryDefinition def, ILGenerator il)
        {
            if (sharedVars.ContainsKey(def))
                return;

            if (!def.IsShared)
            {
                InitSharedVarsOnParameters(sharedVars, def, il);
                return;
            }

            var local = il.DeclareLocal(def.MappedType);
            sharedVars.Add(def, local);
        }