问题
The classes in my data model implement an interface:
public class SomeType : ISomeInterface
public interface ISomeInterface
In my WCF query interceptors, I want to use a common Expression
so that I can use the same filtering logic on multiple types:
[QueryInterceptor("SomeType")]
public Expression<Func<SomeType, bool>> SomeTypeInterceptor()
{
// Return CommonFilter() or extend it with logic unique to SomeType
}
private Expression<Func<ISomeInterface, bool>> CommonFilter()
{
// Use ISomeInterface methods and properties to build expression
// ...
}
The problem is getting the Expression<Func<SomeType, bool>>
to get along with the Expression<Func<ISomeInterface, bool>>
.
Attempt #1
Just returning the common expression does not compile:
[QueryInterceptor("SomeType")]
public Expression<Func<SomeType, bool>> SomeTypeInterceptor()
{
return CommonFilter();
}
with the error:
Cannot implicitly convert type
System.Linq.Expressions.Expression<System.Func<ISomeInterface, bool>>
toSystem.Linq.Expressions.Expression<System.Func<SomeType, bool>>
Attempt #2
Using the interface in the query interceptor definition:
[QueryInterceptor("SomeType")]
public Expression<Func<ISomeInterface, bool>> SomeTypeInterceptor()
compiles, but WCF does not like this, returning an error to the client:
Return type of method 'SomeTypeInterceptor' on type 'DataService' is of type
System.Linq.Expressions.Expression<System.Func<ISomeInterface, System.Boolean>>
but a type assignable toSystem.Linq.Expressions.Expression<System.Func<SomeType, System.Boolean>>
is required for a query interceptor.
Attempt #3
Looking at the questions How can I cast an expression from type interface, to an specific type and C# How to convert an Expression<Func<SomeType>> to an Expression<Func<OtherType>>, I tried implementing this answer:
[QueryInterceptor("SomeType")]
public Expression<Func<SomeType, bool>> SomeTypeInterceptor()
{
Expression<Func<SomeType, bool>> someTypeExpression =
someType => CommonFilter().Compile().Invoke(someType);
return someTypeExpression;
}
but now LINQ to Entities does not like this, returning an error:
LINQ to Entities does not recognize the method 'Boolean Invoke(ISomeInterface)' method, and this method cannot be translated into a store expression.
Is there a way to use common logic in WCF query interceptors?
回答1:
Make the CommonFilter
method generic with required interface constraint on the generic type argument plus class
constraint (needed by LINQ to Entities):
private Expression<Func<T, bool>> CommonFilter<T>()
where T : class, ISomeInterface
{
// Use ISomeInterface methods and properties to build expression
// ...
}
Then use a slightly modified version of your Attempt #1 (which does compile):
[QueryInterceptor("SomeType")]
public Expression<Func<SomeType, bool>> SomeTypeInterceptor()
{
return CommonFilter<SomeType>();
}
来源:https://stackoverflow.com/questions/42908900/common-filtering-logic-in-wcf-query-interceptors-using-interface