Refactoring Method Containing LINQ Queries

I have a little problem solving the best way to refactor a method that contains LINQ queries that are very similar but not identical.

Consider a method that is as follows:

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; } 

This is just an illustration, but imagine that I need to execute a different request (unlike the fact that it uses a different ObjectSet, it uses slightly different fields (object1id vs object2id) and returns a different type. In addition, the requests are the same.

Is there any reasonable way to reorganize such a method? Looks like I missed something obvious. Maybe I need to use the exact method, and I can’t avoid re-writing the request, it just seems to me that I MUST be able to somehow!

Any pointers really appreciated

+6
source share
1 answer

You may have just simplified your script, but the smelly part of your function is casting to SomeObject. Could you just work with the interfaces and (if necessary) bring the result to the call site? You can use your Type1 and Type2 common interface, where id1 and id2 will be displayed as id, for example (or decorate them if you do not control Type1 and Type2)

those.

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

For example, if you have:

  public interface IMyObject {int id {get;}} public class Foo : IMyObject {public int id {get; set;}} public class Bar : IMyObject {public int id {get; set;}} 

You can do:

 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); 

And discard objects after calling the function if you need to.

EDIT: if you are stuck with specific objects and castes, the best refactoring I could come up with is:

 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; } 
+4
source

Source: https://habr.com/ru/post/903193/


All Articles