public DynamicModuleManager(string moduleNamePrefix) { this.states = new List <State>(); this.islands = new Dictionary <State, MethodInfo>(); this.islandsWithPriming = new Dictionary <State, MethodInfo>(); this.sourceDocuments = new Dictionary <string, ISymbolDocumentWriter>(); if (!PartialTrustHelpers.AppDomainFullyTrusted) { moduleNamePrefix = State.ValidateIdentifierString(moduleNamePrefix); } InitDynamicModule(moduleNamePrefix); }
public void Bake(string typeName, string typeNamePrefix, Dictionary <string, byte[]> checksumCache) { // In partial trust, validate the typeName and typeNamePrefix. if (!PartialTrustHelpers.AppDomainFullyTrusted) { typeName = State.ValidateIdentifierString(typeName); typeNamePrefix = State.ValidateIdentifierString(typeNamePrefix); if (checksumCache != null) { bool nullifyChecksumCache = false; foreach (KeyValuePair <string, byte[]> kvpair in checksumCache) { // We use an MD5 hash for the checksum, so the byte array should be 16 elements long. if (!SymbolHelper.ValidateChecksum(kvpair.Value)) { nullifyChecksumCache = true; Trace.WriteLine(SR.DebugSymbolChecksumValueInvalid); break; } } // If we found an invalid checksum, just don't use the cache. if (nullifyChecksumCache) { checksumCache = null; } } } lock (this) { if (this.indexLastBaked < this.states.Count) // there are newly created states. { // Ensure typename is unique. Append a number if needed. int suffix = 1; while (this.dynamicModule.GetType(typeName) != null) { typeName = typeNamePrefix + "_" + suffix.ToString(CultureInfo.InvariantCulture); ++suffix; } TypeBuilder typeBuilder = this.dynamicModule.DefineType(typeName, TypeAttributes.Public | TypeAttributes.Class); for (int i = indexLastBaked; i < this.states.Count; i++) { // Only create the island if debugging is enabled for the state. if (this.states[i].DebuggingEnabled) { MethodBuilder methodBuilder = this.CreateIsland(typeBuilder, this.states[i], false, checksumCache); Fx.Assert(methodBuilder != null, "CreateIsland call should have succeeded"); // Always generate method with priming, for the following scenario: // 1. Start debugging a workflow inside VS, workflow debug session 1 starts (debugStartedAtRoot = true, instrumentation is done) // 2. Workflow persisted, workflow debug session 1 ends // 3. Workflow continued, workflow debug session 2 starts (debugStartedAtRoot = false, instrumentation is skipped because the static dynamicModuleManager is being reused and the instrumentation is done) // 4. PrimeCallStack is called to rebuild the call stack // 5. NullReferenceException will be thrown if MethodInfo with prime is not available MethodBuilder methodBuilderWithPriming = this.CreateIsland(typeBuilder, this.states[i], true, checksumCache); Fx.Assert(methodBuilderWithPriming != null, "CreateIsland call should have succeeded"); // Save information needed to call Type.GetMethod() later. this.states[i].CacheMethodInfo(typeBuilder, methodBuilder.Name); } } // Actual baking. typeBuilder.CreateType(); // Calling Type.GetMethod() is slow (10,000 calls can take ~1 minute). // So defer that to later. this.indexLastBaked = this.states.Count; } } }