Skip to content

Commit 8c6b945

Browse files
Ihar YakimushIhar Yakimush
authored andcommitted
support Cast method
1 parent 6aadabf commit 8c6b945

File tree

5 files changed

+42
-134
lines changed

5 files changed

+42
-134
lines changed

SolrNet.Linq.IntegrationTests/SelectTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ public void AnonymousClassSolrResult()
139139
}
140140

141141
[Fact]
142-
public void SelectDerivedClassCast()
142+
public void SelectDerivedWithCast()
143143
{
144144
IQueryable<DerivedProduct> derivedProducts = Product.SolrOperations.Value.AsQueryable().Where(p => p.Id != null)
145145
.Select(p => new DerivedProduct{Id2 = p.Id}).Where(p => p.Id2 != null);

SolrNet.Linq/Impl/ExecuterExtensions.cs

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ internal static class ExecuterExtensions
1616
{
1717
public static IExecuter<TNew> ChangeType<TNew, TOld>(
1818
this IExecuter<TOld> executer,
19-
MethodCallExpression selectExpression,
19+
MethodCallExpression expression,
2020
SelectExpressionsCollection selectExpressionsCollection)
2121
{
2222
if (executer == null) throw new ArgumentNullException(nameof(executer));
23-
if (selectExpression == null) throw new ArgumentNullException(nameof(selectExpression));
23+
if (expression == null) throw new ArgumentNullException(nameof(expression));
2424
if (selectExpressionsCollection == null) throw new ArgumentNullException(nameof(selectExpressionsCollection));
2525

2626
try
@@ -36,8 +36,8 @@ public static IExecuter<TNew> ChangeType<TNew, TOld>(
3636

3737
ISolrFieldParser fieldParser = oldParser.GetFieldRecursive<ISolrFieldParser>();
3838

39-
ISolrDocumentResponseParser<TNew> docParser = new SelectResponseParser2<TNew, TOld>(oldParser,
40-
new SolrDictionaryDocumentResponseParser(fieldParser), selectExpression,
39+
ISolrDocumentResponseParser<TNew> docParser = new SelectResponseParser<TNew, TOld>(oldParser,
40+
new SolrDictionaryDocumentResponseParser(fieldParser), expression,
4141
selectExpressionsCollection);
4242

4343
ISolrAbstractResponseParser<TNew> parser = new DefaultResponseParser<TNew>(docParser);
@@ -57,21 +57,7 @@ public static IExecuter<TNew> ChangeType<TNew, TOld>(
5757
throw new InvalidOperationException(
5858
$"Unable to change solr query executer from {typeof(TOld)} to {typeof(TNew)}.", e);
5959
}
60-
}
61-
62-
//internal static T GetSingleField<T>(this object instance)
63-
//{
64-
// if (instance == null) throw new ArgumentNullException(nameof(instance));
65-
66-
// BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
67-
// | BindingFlags.Static;
68-
69-
// Type type = instance.GetType();
70-
71-
// FieldInfo field = type.GetFields(bindFlags).Single(info => info.FieldType == typeof(T));
72-
73-
// return (T)field.GetValue(instance);
74-
//}
60+
}
7561

7662
internal static T GetFieldRecursive<T>(this object instance, int limit = 5) where T:class
7763
{
Lines changed: 30 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,55 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4-
using System.Reflection;
4+
using System.Linq.Expressions;
55
using System.Xml.Linq;
66
using SolrNet.Impl;
7-
using SolrNet.Mapping;
7+
using SolrNet.Linq.Expressions;
88

99
namespace 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
}

SolrNet.Linq/Impl/SelectResponseParser2.cs

Lines changed: 0 additions & 55 deletions
This file was deleted.

SolrNet.Linq/SolrQueryProvider.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,12 @@ public IQueryable CreateQuery(Expression expression)
5151

5252
if (expression is MethodCallExpression se)
5353
{
54-
if (se.Arguments.Count > 1 && se.Method.DeclaringType == typeof(Queryable) &&
55-
se.Method.Name == nameof(Queryable.Select))
54+
bool isSelect = se.Arguments.Count == 2 && se.Method.DeclaringType == typeof(Queryable) &&
55+
se.Method.Name == nameof(Queryable.Select);
56+
57+
bool isCast = se.Arguments.Count ==1 && se.Method.DeclaringType == typeof(Queryable) &&
58+
se.Method.Name == nameof(Queryable.Cast);
59+
if (isSelect || isCast)
5660
{
5761
return (IQueryable) Activator.CreateInstance(
5862
typeof(SolrQuery<>).MakeGenericType(elementType),

0 commit comments

Comments
 (0)