Example #1
0
        /// <summary>
        /// Modifies the default constructor to initialize the "__initializedServices" field so that it can ensure that all
        /// services called with the <see cref="IInitialize.Initialize"/> are initialized once per object lifetime.
        /// </summary>
        /// <param name="containerType">The container type.</param>
        /// <param name="module">The module.</param>
        /// <param name="fieldEmitter">The field builder.</param>
        private void AddInitializationMap(TypeDefinition containerType, ModuleDefinition module, FieldBuilder fieldEmitter)
        {
            var initializationMapType = module.Import(typeof(Dictionary<int, int>));
            var initializationMapField = new FieldDefinition("__initializedServices",
                                                             FieldAttributes.Private | FieldAttributes.InitOnly,
                                                             initializationMapType);
            containerType.Fields.Add(initializationMapField);

            var defaultConstructor = containerType.GetDefaultConstructor();
            var body = defaultConstructor.Body;

            // __initializedServices = new Dictionary<int, int>();
            var il = body.GetILProcessor();
            var dictionaryCtor = module.ImportConstructor<Dictionary<int, int>>();
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Newobj, dictionaryCtor);
            il.Emit(OpCodes.Stfld, initializationMapField);
        }
Example #2
0
        /// <summary>
        /// Defines the nested constructors for the singleton type.
        /// </summary>
        /// <param name="module">The target module.</param>
        /// <param name="nestedType">The nested type.</param>
        /// <returns>The static singleton constructor.</returns>
        private static MethodDefinition DefineNestedConstructors(ModuleDefinition module, TypeDefinition nestedType)
        {
            // Define the constructor for the nested t ype
            nestedType.AddDefaultConstructor();
            var defaultConstructor = nestedType.GetDefaultConstructor();
            defaultConstructor.IsPublic = true;

            var cctor = DefineStaticConstructor(module, nestedType);
            cctor.IsPublic = true;

            return cctor;
        }
Example #3
0
        /// <summary>
        /// Modifies the default constructor of a container type so that the jump labels used in the <see cref="IMicroContainer.GetInstance"/> implementation
        /// will be precalculated every time the compiled container is instantiated.
        /// </summary>
        /// <param name="module">The target module.</param>
        /// <param name="jumpTargetField">The field that holds the jump entries.</param>
        /// <param name="targetType">The container type.</param>
        /// <param name="getServiceHash">The hash calculation method.</param>
        /// <param name="serviceMap">The collection that contains the current list of dependencies and their respective implementations.</param>
        /// <param name="jumpTargets">A dictionary that maps dependencies to their respective label indexes.</param>
        private static void AddJumpEntries(ModuleDefinition module, FieldDefinition jumpTargetField, TypeDefinition targetType, MethodReference getServiceHash, IDictionary<IDependency, IImplementation> serviceMap, IDictionary<IDependency, int> jumpTargets)
        {
            var defaultContainerConstructor = targetType.GetDefaultConstructor();

            var body = defaultContainerConstructor.Body;
            var il = body.GetILProcessor();

            // Remove the last instruction and replace it with the jump entry
            // initialization instructions
            RemoveLastInstruction(body);

            // Initialize the jump targets in the default container constructor
            var getTypeFromHandleMethod = typeof(System.Type).GetMethod("GetTypeFromHandle", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
            var getTypeFromHandle = module.Import(getTypeFromHandleMethod);

            // __jumpTargets = new Dictionary<int, int>();
            var dictionaryCtor = module.ImportConstructor<Dictionary<int, int>>();
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Newobj, dictionaryCtor);
            il.Emit(OpCodes.Stfld, jumpTargetField);

            var addMethod = module.ImportMethod<Dictionary<int, int>>("Add");
            var index = 0;
            foreach (var dependency in serviceMap.Keys)
            {
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, jumpTargetField);

                var serviceType = dependency.ServiceType;
                var serviceTypeRef = module.Import(serviceType);

                // Push the service type
                il.Emit(OpCodes.Ldtoken, serviceTypeRef);
                il.Emit(OpCodes.Call, getTypeFromHandle);

                // Push the service name
                var pushName = dependency.ServiceName == null ? il.Create(OpCodes.Ldnull) : il.Create(OpCodes.Ldstr, dependency.ServiceName);
                il.Append(pushName);

                // Calculate the hash code using the service type and service name
                il.Emit(OpCodes.Call, getServiceHash);

                // Map the current dependency to the index
                // that will be used in the GetInstance switch statement
                jumpTargets[dependency] = index;

                il.Emit(OpCodes.Ldc_I4, index++);
                il.Emit(OpCodes.Callvirt, addMethod);
            }
        }