Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 包含LINQ查询的重构方法_C#_Asp.net_Linq_Refactoring - Fatal编程技术网

C# 包含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

我在决定重构一个包含非常相似但不完全相同的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),并返回不同的类型。 除此之外,查询是相同的

有没有一种合理的方法来重构这种方法?我觉得我错过了一些明显的东西。也许我必须使用确切的方法,我无法避免重新编写查询,似乎我应该能够做到


任何非常受欢迎的指针

也许您只是过于简化了您的场景,但您的函数的臭味部分是对某个对象的转换。您不能只使用接口和(如果需要)吗在调用站点强制转换结果?例如,您可以让您的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;
}