How to get a method to return an expression to resolve 'Unrecognised method call in epression' error?
I have the following statement that's throwing an error I don't understand:
return (int) _session.CreateCriteria<T>()
.Add(LambdaSubquery.Property<Fund>(x => x.Id)
.In(GetAvailableIdsPerDataUniverse(x => x.GetDataUniverseId())))
.AddNameSearchCriteria<T>(searchExpression)
.SetProjection(LambdaProjection.Count<T>(e => e.Id))
.UniqueResult();
This is the error:
Unrecognised method call in epression x.GetDataUniverseId()
Background:
I have some different types that I need to perform searches for. Each of these types implement ISearchable
which requires that they have Name
& Id
properties as well as the GetDataUniverseId()
method, which will return an expression representing the dataUniverseId needed for the LambdaProjection
.
The method GetAvailableIdsPerDataUniverse(x => x.GetDataUniverseId())
has the following signature:
protected DetachedCriteria
GetAvailableIdsPerDataUniverse(System.Linq.Expressions.Expression<Func<Fund, object>> dataUniverseId)
and 开发者_运维问答x => x.GetDataUniverseId()
is defined in my Fund
class as
public virtual System.Linq.Expressions.Expression<Func<Fund, object>> GetDataUniverseId()
{
return f => f.Id;
}
and for example as the following in the Company
class:
public virtual Expression<Func<Fund, object>> GetDataUniverseId()
{
return f => f.Company.Id;
}
This works if instead of trying to pass x => x.GetDataUniverseId()
as the parameter, I 'hard-code' f => f.Id
or f => f.Company.Id
. I'd like it if the type being worked on was able to supply the expression it needed rather than me having to pass that expression into every method that uses GetAvailableIdsPerDataUniverse()
. I thought that instead of accessing a property on the inferred type, it could execute a method that would return the expression.
Question:
Is there anything I can do to resolve this error?
Note:
Everything builds fine, so I was a little surprised to see that it threw an error when I ran it. Mostly because when I passed in the expression as a parameter that I 'hard-coded' it worked fine.
Also, I've also tried the following to no avail, where I specify the type I want GetAvailableIdsPerDataUniverse
to act on:
.In(GetAvailableIdsPerDataUniverse<Fund>(x => x.GetDataUniverseId())))
I've been informed that the problem here is that I want the behaviour of polymorphic static methods, but I can't have that because GetDataUniverseId is not an instance method, and I need an instance to be able to use it polymorphically.
The solution, although inefficient because it uses lots of reflection is to use new T()
such that
.Add(LambdaSubquery.Property<Fund>(x => x.Id)
.In(GetAvailableIdsPerDataUniverse(x => x.GetDataUniverseId())))
becomes
.Add(LambdaSubquery.Property<Fund>(x => x.Id)
.In(GetAvailableIdsPerDataUniverse((new T()).GetDataUniverseId())))
The only other issue with this is that the method this exists inside:
public IEnumerable<T> GetEntitiesByName<T>(int pageSize, string searchExpression)
where T : class, ISearchableEntity
must now have the new() constraint, as follows:
public IEnumerable<T> GetEntitiesByName<T>(int pageSize, string searchExpression)
where T : class, ISearchableEntity, new()
I hope somebody finds more use from this than the 'answer' provided by @Sunny
Try:
return (int) _session.CreateCriteria<T>()
.Add(LambdaSubquery.Property<Fund>(x => x.Id)
.In(GetAvailableIdsPerDataUniverse(y => y.GetDataUniverseId())))
.AddNameSearchCriteria<T>(searchExpression)
.SetProjection(LambdaProjection.Count<T>(e => e.Id))
.UniqueResult();
精彩评论