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); }
internal IObjectReaderFactory GetFactory(Type elementType, Type dataReaderType, object mapping, DataLoadOptions options, SqlExpression projection) { for (LinkedListNode <CacheInfo> info = this.list.First; info != null; info = info.Next) { if (elementType == info.Value.elementType && dataReaderType == info.Value.dataReaderType && mapping == info.Value.mapping && DataLoadOptions.ShapesAreEquivalent(options, info.Value.options) && SqlProjectionComparer.AreSimilar(projection, info.Value.projection) ) { // move matching item to head of list to reset its lifetime this.list.Remove(info); this.list.AddFirst(info); return(info.Value.factory); } } return(null); }