public CachingResult <Type> EndGeneration() { Assumes.IsTrue(this._isGenerationStarted); Assumes.IsFalse(this._isGenerationCompleted); CachingResult result = CachingResult.SucceededResult; result = result.MergeResult(this.GenerateGetCatalogMetadata()); result = result.MergeResult(this.GenerateGetCatalogIndex()); Type stubType = this._stubBuilder.CreateType(); this._partsDefinitionBuilder.CreateType(); this._exportsDefinitionBuilder.CreateType(); this._importsDefinitionBuilder.CreateType(); this._isGenerationCompleted = true; return(result.ToResult <Type>(stubType)); }
private CachingResult <MethodInfo> CachePartImportsOrExports <T>(IEnumerable <T> items, TypeBuilder definitionsTable, MethodBuilder stubFactoryMethod, Func <T, IDictionary <string, object> > cacheGenerator, string methodName) // in reality this is only ExportDefinition or ImportDefinition { Assumes.NotNull(items); Assumes.NotNull(definitionsTable); Assumes.NotNull(stubFactoryMethod); Assumes.NotNull(cacheGenerator); Assumes.NotNull(methodName); CachingResult result = CachingResult.SucceededResult; if (!items.Any()) { return(result.ToResult <MethodInfo>(null)); } Type itemType = null; if (typeof(T) == AssemblyCacheGenerator._importDefinitionType) { itemType = AssemblyCacheGenerator._importDefinitionType; } else { itemType = AssemblyCacheGenerator._exportDefinitionType; } // // internal static IEnumerable<T> CreateTs(ComposablePartDefinition owner) // { // T[] items = new ImportDefinition[<count>]; // // IDictionary<string, object> dictionary0 = new Dictionary<string, object>(); // <populate the dictionary with the cache values> // items[0] = CachingStubX.CreateTDefinition(dictinary0); // ... // IDictionary<string, object> dictionary<count-1> = new Dictionary<string, object>(); // <populate the dictionary with the cache values> // items[<count-1>] = CachingStubX.CreateTDefinition(dictinary<count-1>); // ... // return items; // } // Generate the signature MethodBuilder itemsFactoryBuilder = definitionsTable.DefineMethod( methodName, MethodAttributes.Static | MethodAttributes.Assembly, typeof(IEnumerable <T>), new Type[] { AssemblyCacheGenerator._composablePartDefinitionType }); ILGenerator ilGenerator = itemsFactoryBuilder.GetILGenerator(); // // Generate array creation // this._generationServices.LoadValue(ilGenerator, items.Count()); ilGenerator.Emit(OpCodes.Newarr, itemType); // At this point the array is on the stack int index = 0; foreach (T item in items) { // get the cache IDictionary <string, object> cache = cacheGenerator(item); // //items[<index>] = stub.CreateTDefinition(<dictionary>) // ilGenerator.Emit(OpCodes.Dup); // this will load the array on the stack result = result.MergeResult(this._generationServices.LoadValue(ilGenerator, index)); ilGenerator.Emit(OpCodes.Ldarg_0); // load the part definition result = result.MergeResult(this._generationServices.LoadValue(ilGenerator, cache)); // load the dictionary ilGenerator.EmitCall(OpCodes.Call, stubFactoryMethod, null); ilGenerator.Emit(OpCodes.Stelem, itemType); index++; // at this point the duplicate array has been popped from the stack } // just return - the stack already contains the array ilGenerator.Emit(OpCodes.Ret); return(result.ToResult <MethodInfo>(itemsFactoryBuilder)); }
public CachingResult <MethodInfo> CachePartDefinition(ComposablePartDefinition partDefinition) { Assumes.NotNull(partDefinition); CachingResult result = CachingResult.SucceededResult; string methodName = string.Format(CultureInfo.InvariantCulture, "{0}", this._partsCounter); //Ftypeof // public static ComposablePartDefinition<>() // { // // load dictionary // return CachingStubX.CreatePartDefinition(<dictinary>, <importsFactory>, <exportsFactory>); // } // Generate the signature MethodBuilder partFactoryBuilder = this._partsDefinitionBuilder.DefineMethod( methodName, MethodAttributes.Static | MethodAttributes.Public, AssemblyCacheGenerator._composablePartDefinitionType, Type.EmptyTypes); ILGenerator ilGenerator = partFactoryBuilder.GetILGenerator(); // Generate imports caching CachingResult <MethodInfo> importsFactoryResult = this.CachePartImportsOrExports <ImportDefinition>( partDefinition.ImportDefinitions, this._importsDefinitionBuilder, this._createImportDefinitionMethod, (import) => this._cachedCatalogSite.CacheImportDefinition(partDefinition, import), methodName); result = result.MergeErrors(importsFactoryResult.Errors); // Generate exports caching CachingResult <MethodInfo> exportsFactoryResult = this.CachePartImportsOrExports <ExportDefinition>( partDefinition.ExportDefinitions, this._exportsDefinitionBuilder, this._createExportDefinitionMethod, (export) => this._cachedCatalogSite.CacheExportDefinition(partDefinition, export), methodName); result = result.MergeErrors(exportsFactoryResult.Errors); // get the actual cache for the part definition IDictionary <string, object> cache = this._cachedCatalogSite.CachePartDefinition(partDefinition); // // now write the method // // load the cache dictionary on stack result = result.MergeResult(this._generationServices.LoadValue(ilGenerator, cache)); // load the imports function pointer on stack MethodInfo importsFactory = importsFactoryResult.Value; if (importsFactory != null) { ilGenerator.Emit(OpCodes.Ldftn, importsFactory); } else { // load IntPtr.Zero ilGenerator.Emit(OpCodes.Ldsfld, AssemblyCacheGenerator._IntPtr_Zero); } // load the exports function pointer on stack MethodInfo exportsFactory = exportsFactoryResult.Value; if (exportsFactory != null) { ilGenerator.Emit(OpCodes.Ldftn, exportsFactory); } else { // load IntPtr.Zero ilGenerator.Emit(OpCodes.Ldsfld, AssemblyCacheGenerator._IntPtr_Zero); } // and then call into stub.CreatePartDefinition and return ilGenerator.EmitCall(OpCodes.Call, this._createPartDefinitionMethod, null); ilGenerator.Emit(OpCodes.Ret); this._partsCounter++; this.UpdateCatalogIndex(partDefinition, partFactoryBuilder); return(result.ToResult <MethodInfo>(partFactoryBuilder)); }