C# 包含LINQ查询的重构方法
我在决定重构一个包含非常相似但不完全相同的LINQ查询的方法时遇到了一些困难 考虑这样一种方法:C# 包含LINQ查询的重构方法,c#,asp.net,linq,refactoring,C#,Asp.net,Linq,Refactoring,我在决定重构一个包含非常相似但不完全相同的LINQ查询的方法时遇到了一些困难 考虑这样一种方法: public SomeObject GetTheObject(IMyObject genericObject) { Type t = genericObject.GetType(); SomeObject so = null; switch(t.Name) { case "Type1": var object1 = (from o i
public SomeObject GetTheObject(IMyObject genericObject) {
Type t = genericObject.GetType();
SomeObject so = null;
switch(t.Name) {
case "Type1":
var object1 = (from o in object1s where o.object1id == genericObject.id).FirstOrDefault();
so = (SomeObject)object1;
break;
case "Type2":
var object2 = (from o in object2s where o.object2id == genericObject.id).FirstOrDefault();
so = (SomeObject)object2;
break;
default:
break;
}
return so;
}
这只是一个示例,但假设我需要执行不同的查询(不同之处在于它使用不同的ObjectSet,使用稍有不同的字段(object1id vs object2id),并返回不同的类型。
除此之外,查询是相同的
有没有一种合理的方法来重构这种方法?我觉得我错过了一些明显的东西。也许我必须使用确切的方法,我无法避免重新编写查询,似乎我应该能够做到
任何非常受欢迎的指针也许您只是过于简化了您的场景,但您的函数的臭味部分是对某个对象的转换。您不能只使用接口和(如果需要)吗在调用站点强制转换结果?例如,您可以让您的Type1和Type2实现一个公共接口,其中id1和id2作为id公开(如果您不控制Type1和Type2,则装饰它们) 即 你可以做:
var l1 = new List<IMyObject>(){new Foo(){id=1}, new Foo(){id=2}};
var l2 = new List<IMyObject>(){new Bar(){id=1}, new Bar(){id=2}};
var obj1 = Test.GetTheObject(l1, 1);
var obj2 = Test.GetTheObject(l2, 2);
var l1=new List(){new Foo(){id=1},new Foo(){id=2};
var l2=new List(){new Bar(){id=1},new Bar(){id=2};
var obj1=Test.GetTheObject(l1,1);
var obj2=Test.GetTheObject(l2,2);
并在调用函数后强制转换对象(如果必须)
编辑:
如果你被具体的对象和类型转换所困扰,我能想到的最好的重构方法是:
public static SomeObject GetTheObject(IMyObject genericObject) {
Type t = genericObject.GetType();
Func<SomeObject, bool> WhereClause = null;
IEnumerable<SomeObject> objs = null; // IEnumerable<T> is covariant,
// so we can assign it both an IEnumerable<object1>
// and an IEnumerable<object2> (provided object1 and 2 are
// subclasses of SomeObject)
switch(t.Name) {
case "Type1":
WhereClause = o => ((Object1)o).object1id == genericObject.id;
objs = object1s;
break;
case "Type2":
WhereClause = o => ((Object2)o).object2id == genericObject.id;
objs = object2s;
break;
}
var ob = objs
.Where(WhereClause)
.FirstOrDefault();
return (SomeObject)ob;
}
公共静态SomeObject获取对象(IMyObject genericObject){
类型t=generiObject.GetType();
Func WhereClause=null;
IEnumerable objs=null;//IEnumerable是协变的,
//所以我们可以给它分配一个IEnumerable
//和IEnumerable(前提是object1和object2是
//SomeObject的子类)
开关(t.Name){
案例“类型1”:
其中子句=o=>((Object1)o).object1id==generiobject.id;
objs=object1s;
打破
案例“类型2”:
其中子句=o=>((Object2)o).object2id==generiobject.id;
objs=object2s;
打破
}
var ob=objs
.Where(Where条款)
.FirstOrDefault();
返回(SomeObject)ob;
}
是的,我想我确实简化了一些事情,我在使用接口时遇到的问题是,我的查询实际上是对一个需要具体类型的通用存储库的查询。这意味着我现在无法执行Respository,这让我很难过。我想我可以编写另一个存储库,其中t:IMyObject,而不是t:EntityObject目前是这样,但这感觉有点过头了,不过可能是需要的。@dougajmcdonald:我能想到的重构看起来比你的没有多大的改进,但至少它减少了linq代码中的重复…:)谢谢你,我周四有机会的时候会有一场比赛,我希望摆脱切换逻辑,因为在我的现实生活中,我可能有10-12个选项,我不希望用case语句阻塞屏幕!再说一次,这可能是唯一的选择!我尝试了反射,但无法通过LINQ语句(“从object1s中的o到o.object1id”)。您应该研究动态生成LINQ语句。嗨,Graham,这当然是一个选项,除了我试图将DAL封装在存储库中这一事实,这使得我在动态生成查询的方法上受到限制。我试图构建一个工厂来返回我想要的具体存储库实例。但这让我陷入了与我向Paolo描述的类似的情况,即因为我的存储库需要一个具体的EntityObject类型,所以我无法基于接口创建一个EntityObject类型。
var l1 = new List<IMyObject>(){new Foo(){id=1}, new Foo(){id=2}};
var l2 = new List<IMyObject>(){new Bar(){id=1}, new Bar(){id=2}};
var obj1 = Test.GetTheObject(l1, 1);
var obj2 = Test.GetTheObject(l2, 2);
public static SomeObject GetTheObject(IMyObject genericObject) {
Type t = genericObject.GetType();
Func<SomeObject, bool> WhereClause = null;
IEnumerable<SomeObject> objs = null; // IEnumerable<T> is covariant,
// so we can assign it both an IEnumerable<object1>
// and an IEnumerable<object2> (provided object1 and 2 are
// subclasses of SomeObject)
switch(t.Name) {
case "Type1":
WhereClause = o => ((Object1)o).object1id == genericObject.id;
objs = object1s;
break;
case "Type2":
WhereClause = o => ((Object2)o).object2id == genericObject.id;
objs = object2s;
break;
}
var ob = objs
.Where(WhereClause)
.FirstOrDefault();
return (SomeObject)ob;
}