C# 在wcf上序列化谓词
我有一个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,因此我希望使用(相对)简单的
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
等集合)。