Common filtering logic in WCF query interceptors using interface

徘徊边缘 提交于 2019-12-24 06:22:49

问题


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>> to System.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 to System.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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!