Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在计算IQueryable之前指定延迟操作_C#_Linq_Iqueryable - Fatal编程技术网

C# 在计算IQueryable之前指定延迟操作

C# 在计算IQueryable之前指定延迟操作,c#,linq,iqueryable,C#,Linq,Iqueryable,我想对从IQueryable返回的实体执行一些后处理,但我想在计算查询之前指定该后处理。例如: IQueryable<Client> GetClients() { return _context.Set<Client>() .PostProcess(c => c.MobileNumber = c.MobileNumber.Replace(" ", "")); } Client GetClient(int id) { return G

我想对从
IQueryable
返回的实体执行一些后处理,但我想在计算查询之前指定该后处理。例如:

IQueryable<Client> GetClients()
{
    return _context.Set<Client>()
        .PostProcess(c => c.MobileNumber = c.MobileNumber.Replace(" ", ""));
}

Client GetClient(int id)
{
    return GetClients()
        .FirstOrDefault(c => c.Id == id);
}
IQueryable GetClients()
{
返回_context.Set()
.PostProcess(c=>c.MobileNumber=c.MobileNumber.Replace(“,”);
}
客户端GetClient(int-id)
{
返回GetClients()
.FirstOrDefault(c=>c.Id==Id);
}
在上面的示例中,我希望从上述两种方法返回的每个
客户端
都从其手机号码中删除所有空格。这可能吗?

编辑:这是个坏主意 它适用于OP中所述的简单情况,但任何进一步的
IQueryable
扩展(例如
.Where()
子句)都将放弃后处理行为。我不确定在技术上是否可以做我想做的事情,现在我想起来了,我甚至不确定在简单的情况下语义会是什么。尽管如此,这个简单的案例仍然有效,并且可以很方便地让事情保持流畅


原件: 我想我会分享我的方法,以防有人觉得它有用(或者对这是个坏主意的原因发表评论)。该解决方案使用两个装饰器延迟后处理操作,直到执行查询为止,并使用扩展方法设置它们:

public static class QueryableExtensions
{
    public static IQueryable<T> PostProcess<T>(this IQueryable<T> source, Action<T> postProcessor) where T : class
    {
        return new QueryableWrapper<T>(source, postProcessor);
    }

    // wraps IQueryProvider.Execute methods with post-processing action
    class QueryProviderWrapper<T> : IQueryProvider where T : class
    {
        private readonly IQueryProvider _wrapped;
        private readonly Action<T> _postProcessor;

        public QueryProviderWrapper(IQueryProvider wrapped, Action<T> postProcessor)
        {
            _wrapped = wrapped;
            _postProcessor = postProcessor;
        }

        public IQueryable CreateQuery(Expression expression)
        {
            return _wrapped.CreateQuery(expression);
        }

        public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
        {
            return _wrapped.CreateQuery<TElement>(expression);
        }

        public object Execute(Expression expression)
        {
            var result = _wrapped.Execute(expression);
            var asT = result as T;
            if (asT != null)
                _postProcessor(asT);
            return result;
        }

        public TResult Execute<TResult>(Expression expression)
        {
            var result = _wrapped.Execute<TResult>(expression);
            var asT = result as T;
            if (asT != null)
                _postProcessor(asT);
            return result;
        }
    }

    // wraps IQueryable.GetEnumerator() with post-processing action
    class QueryableWrapper<T> : IQueryable<T> where T : class
    {
        private readonly IQueryable<T> _wrapped;
        private readonly Action<T> _postProcessor;
        private readonly IQueryProvider _provider;

        public QueryableWrapper(IQueryable<T> wrapped, Action<T> postProcessor)
        {
            _wrapped = wrapped;
            _postProcessor = postProcessor;
            _provider = new QueryProviderWrapper<T>(_wrapped.Provider, postProcessor);
        }

        public Expression Expression
        {
            get { return _wrapped.Expression; }
        }

        public Type ElementType
        {
            get { return _wrapped.ElementType; }
        }

        public IQueryProvider Provider
        {
            get { return _provider; }
        }

        public IEnumerator<T> GetEnumerator()
        {
            return _wrapped
                .AsEnumerable()
                .Do(_postProcessor)
                .GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}
公共静态类QueryableExtensions
{
公共静态IQueryable后处理(此IQueryable源,操作后处理器),其中T:class
{
返回新的QueryableWrapper(源,后处理器);
}
//包装IQueryProvider。使用后期处理操作执行方法
类QueryProviderWrapper:IQueryProvider,其中T:class
{
私有只读IQueryProvider _包装;
专用只读操作\u后处理器;
公共QueryProviderWrapper(IQueryProvider包装,操作后处理器)
{
_包裹的=包裹的;
_后处理器=后处理器;
}
公共IQueryable CreateQuery(表达式)
{
返回_wrapped.CreateQuery(表达式);
}
公共IQueryable CreateQuery(表达式)
{
返回_wrapped.CreateQuery(表达式);
}
公共对象执行(表达式)
{
var result=_wrapped.Execute(表达式);
var asT=结果为T;
如果(asT!=null)
_后处理器(asT);
返回结果;
}
公共TResult执行(表达式)
{
var result=_wrapped.Execute(表达式);
var asT=结果为T;
如果(asT!=null)
_后处理器(asT);
返回结果;
}
}
//使用后期处理操作包装IQueryable.GetEnumerator()
类QueryableWrapper:IQueryable,其中T:class
{
私人只读可读取包装;
专用只读操作\u后处理器;
专用只读IQueryProvider\u提供程序;
公共QueryableWrapper(IQueryable包装,操作后处理器)
{
_包裹的=包裹的;
_后处理器=后处理器;
_provider=新的QueryProviderWrapper(_wrapped.provider,后处理器);
}
公开表达
{
获取{return\u wrapped.Expression;}
}
公共类型ElementType
{
获取{return\u wrapped.ElementType;}
}
公共IQueryProvider提供程序
{
获取{return\u provider;}
}
公共IEnumerator GetEnumerator()
{
返回包装
.可计算的()
.Do(_后处理器)
.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
返回GetEnumerator();
}
}
}
GetEnumerator()
decorator使用
.Do()
扩展方法,该方法类似于
Select
ForEach
之间的交叉:它被延迟调用,但执行
操作
并返回
T