我希望能够将像DRY和SOLID这样的面向对象原则应用于一些Linq Projections。使用已编译的查询或传递的参数,我可以成功地将这些应用到Linq的其余部分,而不是在预测中。
如果这是不可能的,请告诉我,我必须选择我的替代解决方案之一(如下所述),如果可能的话如何,或者如果我遗漏某些东西,还有另一种替代实施方案将满足目标。
在高级别,我希望能够使用标准Linq Query或CompiledQuery动态控制Linq Projection中使用的类型。我在我的示例和实际代码中使用Linq to Entities,但问题应该适用于核心Linq。
以下是非动态且不能解决问题的简单示例。修复它们以始终为每种类型使用FooUser。我希望能够动态控制在投影中创建的用户类型,所有这些都将基于一个通用的IUser接口。这将是或可能类似于我如何控制查询过滤的类型。
我正在尝试遵循DRY,SOLID,并且还试图避免使用枚举来处理这是典型的代码气味。然而,在我的所有尝试和研究中,我似乎不得不采取以下解决方案之一。
为每种类型实施查询 这些都是相同的,除了 他们过滤的类型和类型 用于投影。虽然这个 我可以违反DRY和OCP 将其封装在一个单独的内容中 上课,让他们紧密相连 作为编译的查询。这将 如果我添加,则要求更改类 一个新类型或如何查询 数据发生了变化。
实现具有类型的枚举,并使用其类型为属性的更通用的User类。然而,这将导致我必须在几个位置使用枚举并引入长句例句来处理它们,我想避免这种情况。
我希望不必在不同的邪恶之间做出选择,并且有一个符合所有SOLID原则和DRY的实现。但是,如果我必须认为我最终会得到它的第一个或一个版本。
标准简单Linq查询
using (MyEntities context = new MyEntities())
{
var results = from u in context.Users
where u.UserType == type
select new FooUser
{
Id = u.UserID,
Name = u.UserName,
Location = u.UserLocation
};
}
上述查询的编译版本
private static readonly Func<MyEntities, int, IQueryable<FooUser>> query = CompiledQuery.Compile<MyEntities, int, IQueryable<FooUser>>(
(context, type) => from u in context.Users
where u.UserType == type
select new FooUser
{
Id = u.UserID,
Name = u.UserName,
Location = u.UserLocation
});-
答案 0 :(得分:0)
我找到了一种使用标准方法调用来实现此目的的方法。我还没弄清楚如何用编译的查询来做这件事,看起来不太可能。
我不知道关于泛型的where语句的Constructor Constraint I.这可以满足我的需求。我很乐意用编译的查询来做这件事,但是对这个解决方案感到高兴。
public IQueryable<IUser> FooMethod<T>(int type) where T : IUser, new()
{
using (MyEntities context = new MyEntities())
{
var results = from u in context.users
where u.usertype == type
select new T
{
id = u.UserId,
name = u.UserName,
location = u.Userlocation
};
return results;
}
}
我选择发布答案而不是删除问题有两个原因,以防其他人正在寻找类似的东西,这可能会有所帮助。当然,我可能会离开基地,让人们在事物上打洞并看到我们能想出的更好的东西总是很有趣。