我在确定重构包含非常相似但不完全相同的LINQ查询的方法的最佳方法时遇到了一些麻烦。
考虑一下这些方法:
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)并返回不同的类型。 除此之外,查询是相同的。
有没有合理的方法来重构这种方法?感觉就像我错过了一些明显的东西。也许我必须使用确切的方法,我不能避免重写查询,看起来我应该能够以某种方式!
任何指针都非常赞赏
答案 0 :(得分:4)
也许你刚刚过度简化了你的场景,但你的函数的臭部分是对SomeObject的强制转换。难道你不能只使用接口和(如果需要)在调用站点转换结果?例如,你可以让你的Type1和Type2实现一个公共接口,其中id1和id2作为id公开(如果你不控制Type1和Type2,则装饰它们)
即。
public static IMyObject GetTheObject(List<IMyObject> theList, int id)
{
var ret = (from o in theList
where o.id==id
select o).FirstOrDefault();
return ret;
}
例如,如果你有:
public interface IMyObject {int id {get;}}
public class Foo : IMyObject {public int id {get; set;}}
public class Bar : IMyObject {public int id {get; set;}}
你可以这样做:
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;
}