1313using Xtensive . Reflection ;
1414
1515using Factory = System . Func <
16- System . Linq . Expressions . Expression ,
17- System . Collections . Generic . IEnumerable < System . Linq . Expressions . ParameterExpression > ,
18- System . Linq . Expressions . LambdaExpression
16+ System . Linq . Expressions . Expression ,
17+ System . Linq . Expressions . ParameterExpression [ ] ,
18+ System . Linq . Expressions . LambdaExpression
19+ > ;
20+
21+ using SlowFactory = System . Func <
22+ System . Linq . Expressions . Expression ,
23+ System . Collections . Generic . IEnumerable < System . Linq . Expressions . ParameterExpression > ,
24+ System . Linq . Expressions . LambdaExpression
25+ > ;
26+
27+ using FastFactory = System . Func <
28+ System . Linq . Expressions . Expression ,
29+ string ,
30+ bool ,
31+ System . Collections . Generic . IReadOnlyList < System . Linq . Expressions . ParameterExpression > ,
32+ System . Linq . Expressions . LambdaExpression
1933 > ;
2034
2135namespace Xtensive . Linq
2236{
2337 internal sealed class LambdaExpressionFactory
2438 {
39+ private static readonly Type [ ] internalFactorySignature = new [ ] {
40+ typeof ( Expression ) , typeof ( string ) , typeof ( bool ) , typeof ( IReadOnlyList < ParameterExpression > )
41+ } ;
42+
2543 private static readonly object _lock = new object ( ) ;
2644 private static volatile LambdaExpressionFactory instance ;
2745
@@ -32,27 +50,54 @@ public static LambdaExpressionFactory Instance {
3250 return instance ;
3351 }
3452 }
35-
36- private readonly MethodInfo factoryMethod ;
53+
3754 private readonly ThreadSafeDictionary < Type , Factory > cache ;
55+ private readonly Func < Type , Factory > createHandler ;
56+ private readonly MethodInfo slowFactoryMethod ;
3857
3958 public LambdaExpression CreateLambda ( Type delegateType , Expression body , ParameterExpression [ ] parameters )
4059 {
41- var factory = cache . GetValue ( delegateType , ( _delegateType , _this ) => _this . CreateFactory ( _delegateType ) , this ) ;
60+ var factory = cache . GetValue ( delegateType , createHandler ) ;
4261 return factory . Invoke ( body , parameters ) ;
4362 }
44-
63+
4564 public LambdaExpression CreateLambda ( Expression body , ParameterExpression [ ] parameters )
4665 {
4766 var delegateType = DelegateHelper . MakeDelegateType ( body . Type , parameters . Select ( p => p . Type ) ) ;
4867 return CreateLambda ( delegateType , body , parameters ) ;
4968 }
5069
5170 #region Private / internal methods
52-
53- private Factory CreateFactory ( Type delegateType )
71+
72+ internal Factory CreateFactorySlow ( Type delegateType )
73+ {
74+ var factory = ( SlowFactory ) Delegate . CreateDelegate (
75+ typeof ( SlowFactory ) , slowFactoryMethod . MakeGenericMethod ( delegateType ) ) ;
76+
77+ return ( body , parameters ) => factory . Invoke ( body , parameters ) ;
78+ }
79+
80+ internal static Factory CreateFactoryFast ( Type delegateType )
5481 {
55- return ( Factory ) Delegate . CreateDelegate ( typeof ( Factory ) , factoryMethod . MakeGenericMethod ( delegateType ) ) ;
82+ var method = typeof ( Expression < > ) . MakeGenericType ( delegateType ) . GetMethod (
83+ "Create" , BindingFlags . Static | BindingFlags . NonPublic , null , internalFactorySignature , null ) ;
84+
85+ if ( method == null ) {
86+ return null ;
87+ }
88+
89+ var factory = ( FastFactory ) Delegate . CreateDelegate ( typeof ( FastFactory ) , null , method ) ;
90+ return ( body , parameters ) => factory . Invoke ( body , null , false , parameters ) ;
91+ }
92+
93+ internal static bool CanUseFastFactory ( )
94+ {
95+ try {
96+ return CreateFactoryFast ( typeof ( Func < int > ) ) != null ;
97+ }
98+ catch {
99+ return false ;
100+ }
56101 }
57102
58103 #endregion
@@ -62,11 +107,13 @@ private Factory CreateFactory(Type delegateType)
62107 private LambdaExpressionFactory ( )
63108 {
64109 cache = ThreadSafeDictionary < Type , Factory > . Create ( new object ( ) ) ;
65- factoryMethod = typeof ( Expression ) . GetMethods ( )
66- . Where ( m => m . IsGenericMethod
67- && m . Name == "Lambda"
68- && m . GetParameters ( ) [ 1 ] . ParameterType == typeof ( IEnumerable < ParameterExpression > ) )
69- . Single ( ) ;
110+
111+ slowFactoryMethod = typeof ( Expression ) . GetMethods ( ) . Single ( m =>
112+ m . IsGenericMethod &&
113+ m . Name == "Lambda" &&
114+ m . GetParameters ( ) [ 1 ] . ParameterType == typeof ( IEnumerable < ParameterExpression > ) ) ;
115+
116+ createHandler = CanUseFastFactory ( ) ? ( Func < Type , Factory > ) CreateFactoryFast : CreateFactorySlow ;
70117 }
71118 }
72119}
0 commit comments