private void CompileCapturedMethod(DynamicTypeGenerator gen, SqlExpression expression, Type elementType) { TypeBuilder tb = ObjectReaderCompiler.CaptureModule.DefineType("reader_type_" + ObjectReaderCompiler.GetNextId()); MethodBuilder mb = tb.DefineMethod( "Read_" + elementType.Name, MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, elementType, new Type[] { typeof(ObjectMaterializer<>).MakeGenericType(this.dataReaderType) } ); gen.GenerateBody(mb.GetILGenerator(), (SqlExpression)SqlDuplicator.Copy(expression)); tb.CreateType(); }
private DynamicMethod CompileDynamicMethod(DynamicTypeGenerator gen, SqlExpression expression, Type elementType) { Type objectReaderType = typeof(ObjectMaterializer<>).MakeGenericType(this.dataReaderType); DynamicMethod dm = new DynamicMethod( "Read_" + elementType.Name, elementType, new Type[] { objectReaderType }, true ); gen.GenerateBody(dm.GetILGenerator(), expression); return dm; }
public IObjectReaderFactory Compile(SqlExpression expression, Type elementType) { object mapping = this.services.Context.Mapping.Identity; DataLoadOptions options = this.services.Context.LoadOptions; IObjectReaderFactory factory = null; ObjectReaderFactoryCache cache = null; bool canBeCompared = SqlProjectionComparer.CanBeCompared(expression); if(canBeCompared) { cache = (ObjectReaderFactoryCache)Thread.GetData(cacheSlot); if(cache == null) { cache = new ObjectReaderFactoryCache(maxReaderCacheSize); Thread.SetData(cacheSlot, cache); } factory = cache.GetFactory(elementType, this.dataReaderType, mapping, options, expression); } if(factory == null) { DynamicTypeGenerator gen = new DynamicTypeGenerator(this, elementType); #if DEBUG if(ObjectReaderCompiler.CaptureModule != null) { this.CompileCapturedMethod(gen, expression, elementType); } #endif DynamicMethod dm = this.CompileDynamicMethod(gen, expression, elementType); Type fnMatType = typeof(Func<,>).MakeGenericType(typeof(ObjectMaterializer<>).MakeGenericType(this.dataReaderType), elementType); var fnMaterialize = (Delegate)dm.CreateDelegate(fnMatType); Type factoryType = typeof(ObjectReaderFactory<,>).MakeGenericType(this.dataReaderType, elementType); factory = (IObjectReaderFactory)Activator.CreateInstance( factoryType, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { fnMaterialize, gen.NamedColumns, gen.Globals, gen.Locals }, null ); if(canBeCompared) { expression = new SourceExpressionRemover().VisitExpression(expression); cache.AddFactory(elementType, this.dataReaderType, mapping, options, expression, factory); } } return factory; }