11using System ;
22using System . Collections . Generic ;
33using System . Linq ;
4- using System . Reflection ;
4+ using System . Linq . Expressions ;
55using System . Xml . Linq ;
66using SolrNet . Impl ;
7- using SolrNet . Mapping ;
7+ using SolrNet . Linq . Expressions ;
88
99namespace SolrNet . Linq . Impl
1010{
1111 public class SelectResponseParser < TNew , TOld > : ISolrDocumentResponseParser < TNew >
1212 {
13- private readonly ConstructorInfo CtorInfo = typeof ( TNew ) . GetConstructors ( ) . Single ( ) ;
14- private readonly ISolrFieldParser parser ;
13+ private readonly ISolrDocumentResponseParser < TOld > _inner ;
14+ private readonly ISolrDocumentResponseParser < Dictionary < string , object > > _dictionaryParser ;
15+ private readonly MethodCallExpression _selectCall ;
16+ private readonly SelectExpressionsCollection _selectState ;
1517
16- public SelectResponseParser ( ISolrFieldParser parser )
18+ public SelectResponseParser ( ISolrDocumentResponseParser < TOld > inner , ISolrDocumentResponseParser < Dictionary < string , object > > dictionaryParser , MethodCallExpression selectCall , SelectExpressionsCollection selectState )
1719 {
18- this . parser = parser ?? throw new ArgumentNullException ( nameof ( parser ) ) ;
20+ _inner = inner ?? throw new ArgumentNullException ( nameof ( inner ) ) ;
21+ _dictionaryParser = dictionaryParser ?? throw new ArgumentNullException ( nameof ( dictionaryParser ) ) ;
22+ _selectCall = selectCall ;
23+ _selectState = selectState ;
1924 }
20-
2125 public IList < TNew > ParseResults ( XElement parentNode )
2226 {
23- List < TNew > objList = new List < TNew > ( ) ;
2427 if ( parentNode == null )
25- return ( IList < TNew > ) objList ;
26- foreach ( XElement element in parentNode . Elements ( ( XName ) "doc" ) )
27- objList . Add ( this . ParseDocument ( element ) ) ;
28- return ( IList < TNew > ) objList ;
28+ return null ;
29+
30+ List < TNew > result = new List < TNew > ( ) ;
31+ var docs = this . _dictionaryParser . ParseResults ( parentNode ) ;
32+ IList < TOld > olds = this . _inner . ParseResults ( parentNode ) ;
33+
34+ for ( int i = 0 ; i < olds . Count ; i ++ )
35+ {
36+ result . Add ( this . GetResult ( olds [ i ] , docs [ i ] ) ) ;
37+ }
38+
39+ return result ;
2940 }
3041
31- public TNew ParseDocument ( XElement node )
42+ private TNew GetResult ( TOld old , Dictionary < string , object > dictionary )
3243 {
33- Dictionary < string , XElement > fields = node . Elements ( ) . ToDictionary ( element => element . Attribute ( ( XName ) "name" ) . Value ) ;
34-
35- List < object > args = new List < object > ( fields . Count ) ;
36- foreach ( ParameterInfo p in CtorInfo . GetParameters ( ) )
37- {
38- object obj = p . ParameterType . IsValueType ? Activator . CreateInstance ( p . ParameterType ) : null ;
39- if ( fields . ContainsKey ( p . Name ) )
40- {
41- if ( p . ParameterType == typeof ( XElement ) )
42- {
43- string text = fields [ p . Name ] . ToString ( ) ;
44- try
45- {
46-
47- obj = XElement . Parse ( text ) ;
48- }
49- catch ( Exception e )
50- {
51- throw new InvalidOperationException (
52- $ "Unable to set value for { p . Name } . Value { text } can't be parsed to XElement", e ) ;
53- }
54- }
55- else if ( this . parser . CanHandleSolrType ( fields [ p . Name ] . Name . LocalName ) &&
56- this . parser . CanHandleType ( p . ParameterType ) )
57- {
58- obj = this . parser . Parse ( fields [ p . Name ] , p . ParameterType ) ;
44+ ReplaceCalculatedVisitor visitor = new ReplaceCalculatedVisitor ( this . _selectState , dictionary ) ;
5945
60- if ( obj != null )
61- {
62- if ( ! p . ParameterType . IsAssignableFrom ( obj . GetType ( ) ) )
63- {
64- throw new InvalidOperationException (
65- $ "Unable to set value for { p . Name } . Value { obj } of type { obj . GetType ( ) } not assignable to type { p . ParameterType } ") ;
66- }
67- }
68- else if ( p . ParameterType . IsValueType )
69- {
70- throw new InvalidOperationException (
71- $ "Unable to set value for { p . Name } . Value null not assignable to type { p . ParameterType } ") ;
72- }
73- }
74- }
46+ LambdaExpression lambdaExpression = ( LambdaExpression ) this . _selectCall . Arguments [ 1 ] . StripQuotes ( ) ;
7547
76- args . Add ( obj ) ;
77- }
48+ LambdaExpression expression = ( LambdaExpression ) visitor . Visit ( lambdaExpression ) ;
49+
50+ object result = expression . Compile ( ) . DynamicInvoke ( old ) ;
7851
79- return ( TNew ) CtorInfo . Invoke ( args . ToArray ( ) ) ;
52+ return ( TNew ) result ;
8053 }
8154 }
8255}
0 commit comments