Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.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# 在wcf上序列化谓词_C#_Wcf_Generics_Predicate - Fatal编程技术网

C# 在wcf上序列化谓词

C# 在wcf上序列化谓词,c#,wcf,generics,predicate,C#,Wcf,Generics,Predicate,我有一个WCF服务,它公开了一系列返回业务对象的方法。它有一个很好的存储库层,使用如下接口方法: IEnumerable<User> GetUsers(Func<User, bool> predicate); IEnumerable<User> GetUsers(IEnumerable<Filter> filters); 现在我想公开这一点,任何过滤器都可以考虑WCF接口。非.Net客户端需要能够访问WCF api,因此我希望使用(相对)简单的

我有一个WCF服务,它公开了一系列返回业务对象的方法。它有一个很好的存储库层,使用如下接口方法:

IEnumerable<User> GetUsers(Func<User, bool> predicate);
IEnumerable<User> GetUsers(IEnumerable<Filter> filters);
现在我想公开这一点,任何过滤器都可以考虑WCF接口。非.Net客户端需要能够访问WCF api,因此我希望使用(相对)简单的类型

我有一个包含属性名称和值的筛选器对象:

[DataContract] public class Filter {
    [DataMember] public string Property { get; set; }
    [DataMember] public string Value { get; set; }
}
现在我可以公开一个WCF方法,如下所示:

IEnumerable<User> GetUsers(Func<User, bool> predicate);
IEnumerable<User> GetUsers(IEnumerable<Filter> filters);
IEnumerable GetUsers(IEnumerable过滤器);
然后,我可以在客户端过滤器中基于传入的内容构建谓词。现在情况变得一团糟:

private static Expression<Func<T, bool>> GetPredicate<T>(Filter filter)
{
  var knownPredicates = GetKnownPredicates<T>(filter.Value);
  var t = typeof(T);
  return knownPredicates.ContainsKey(t) && knownPredicates[t].ContainsKey(filter.Property)
           ? knownPredicates[t][filter.Property]
           : True<T>();
}

private static Dictionary<Type, Dictionary<string, Expression<Func<T, bool>>>> GetKnownPredicates<T>(string value)
{
  // ReSharper disable PossibleNullReferenceException
  return new Dictionary<Type, Dictionary<string, Expression<Func<T, bool>>>>
  {
    {
      typeof (User), new Dictionary<string, Expression<Func<T, bool>>>
      {
        { "Forename", x => (x as User).Forename == value },
        { "IsAdult", x => (x as User).IsAdult.ToString() == value },
        ...
      }
    },
    {
      typeof (Group), new Dictionary<string, Expression<Func<T, bool>>>
      {
        { "Name", x => (x as Group).Name == value },
        ...
      }
    },
    ...
  };
  // ReSharper restore PossibleNullReferenceException
}
私有静态表达式GetPredicate(过滤器过滤器)
{
var knownPredicates=GetKnownPredicates(filter.Value);
var t=类型(t);
返回knownPedicates.ContainsKey(t)和&knownPedicates[t].ContainsKey(filter.Property)
?知识预测[t][filter.Property]
:True();
}
私有静态字典GetKnownPedicates(字符串值)
{
//ReSharper禁用PossibleNullReferenceException
返回新词典
{
{
typeof(用户),新字典
{
{“Forename”,x=>(x作为用户)。Forename==value},
{“IsAdult”,x=>(x作为用户).IsAdult.ToString()==value},
...
}
},
{
typeof(组),新词典
{
{“Name”,x=>(x作为组)。Name==value},
...
}
},
...
};
//ReSharper还原可能的NullReferenceException
}

在我开始编写getKnownPedicates方法之前,代码并不是很糟糕。现在是了。如何修复它?

如果您想变得超级花哨,可以使用该类根据传入的筛选器动态构建谓词。您知道要搜索的类型,所以只需使用Filter.Property,然后使用Filter.Value的常量表达式。用它们组成一个相等的表达式,你就快到终点了


习惯于编写表达式可能是一件痛苦的事情,但调试器确实很有帮助,它会在编写表达式时向您显示表达式的代码,因此请深入并尝试

绝对没有办法让你的
功能通过网络。该表达式被存储并将被jitted,并且将存在于客户端世界中


请记住,基本上您要做的是使用
u=>u.Roles.Contains(plebRole)
编译匿名客户端函数。因此,您将得到一些用户,稍后将在客户端进行过滤。

当然,您需要考虑安全性,因为您可能不希望让最终用户查询类的任何属性。也许属性属性带有一个自定义的“OK to Filter”属性,您可以在创建过滤器之前检查该属性。酷,这就是我想要探索的路线。我不担心安全性,因为我在请求对象中有一个auth令牌,并且我有一个机制来决定是否处理请求。这都是真的,但通常有几种方法可以剥猫皮。我并不是逐字逐句的意思。我已经用
IEnumerable
完成了。我可以向过滤器添加属性,以指定运算符和比较类型之类的内容。真正的问题是如何将筛选器转换为谓词,而不指定每个可能的属性和比较类型(例如
StartsWith()
和处理
user.Roles
等集合)。