包含LINQ查询的重构方法

dou*_*ald 6 c# linq asp.net refactoring

我在决定重构包含非常相似但不完全相同的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;
}
Run Code Online (Sandbox Code Playgroud)

这只是一个例子,但想象一下我需要执行不同的查询(不同之处在于它使用不同的ObjectSet,使用稍微不同的字段(object1id vs object2id)并返回不同的类型.除此之外,查询是相同.

是否有一种合理的方法来重构这种方法?感觉就像我错过了一些明显的东西.也许我必须使用确切的方法,我无法避免重写查询,它似乎我应该能够以某种方式!

任何指针都非常感激

Pao*_*lla 4

也许您只是过于简化了您的场景,但是您的函数的难闻部分是对 SomeObject 的强制转换。难道您不能只使用接口并(如果需要)在调用站点强制转换结果吗?例如,您可以让 Type1 和 Type2 实现一个通用接口,其中 id1 和 id2 作为 id 公开(或者如果您不控制 Type1 和 Type2,则装饰它们)

IE

public static IMyObject GetTheObject(List<IMyObject> theList,  int id)
{
    var ret = (from o in theList
        where o.id==id
        select o).FirstOrDefault();

    return ret;
}
Run Code Online (Sandbox Code Playgroud)

例如,如果您有:

    public interface IMyObject {int id {get;}}

    public class Foo : IMyObject {public int id {get; set;}}
    public class Bar : IMyObject {public int id {get; set;}}
Run Code Online (Sandbox Code Playgroud)

你可以做:

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);
Run Code Online (Sandbox Code Playgroud)

如果需要的话,可以在调用函数后强制转换对象。

编辑:如果你被具体的对象和演员困住了,我能想到的最好的重构是:

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;
}
Run Code Online (Sandbox Code Playgroud)