2012-04-20 1 views
2

Я работаю над приложением, где мне нужно вызвать один из двух методов данных, основанный на родовом типе вызывающего класса. Например, если T имеет тип Foo, я буду называть data.GetFoo():Вызов метода DAL на основе типа

private static List<T> GetObjectList(DateTime mostRecentProcessedReadTime) 
{ 
    using (MesReportingDal data = new MesReportingDal()) 
    { 
     return data.GetFoo(mostRecentProcessedReadTime); // Notice GetFoo() 
    } 
} 

И если T имеет тип бара, я позвоню data.GetBar():

private static List<T> GetObjectList(DateTime mostRecentProcessedReadTime) 
{ 
    using (MesReportingDal data = new MesReportingDal()) 
    { 
     return data.GetBar(mostRecentProcessedReadTime); // Notice GetBar() 
    } 
} 

До сих пор мне нужен только один метод DAL, потому что все типы были получены одинаково. Теперь мне нужно позвонить по одному из двух методов, в зависимости от типа T.

Я пытаюсь избежать чего-то вроде этого:

private static List<T> GetObjectList(DateTime mostRecentProcessedReadTime) 
{ 
    using (MesReportingDal data = new MesReportingDal()) 
    { 
     if (T is Foo) { return data.GetFoo(mostRecentProcessedReadTime); } 
     if (T is Bar) { return data.GetBar(mostRecentProcessedReadTime); } 
    } 
} 

Это нарушает OCP. Есть ли элегантный способ справиться с этим, поэтому я могу избавиться от моего заявления if?

Edit - Это то, что типы похожи

public partial class Foo1 : IDataEntity { } 
public partial class Foo2 : IDataEntity { } 
public partial class Bar1 : IDataEntity { } 
public partial class Bar2 : IDataEntity { } 

Этого Фоосом и Столбики элементы DBML, используемые с Linq-на-SQL.

+0

У вас есть контроль над классами «Т» - они могут быть изменены, у вас есть базовый интерфейс/класс и т. Д. – NSGaga

+0

См. Мое редактирование. Это помогает? –

+0

Если вы не хотите менять Foo *, Bar *, и он должен быть GetFoo, GetBar - not Get(), как предлагал ataddeini (если я правильно понял?). Как вы собираетесь «вызывать» GetObjectList()? вы определяете, например, Foo, Bar перед вызовом (так что у вас есть, например,типизированная переменная) - или вы хотите назвать это довольно широко (используя T из другого общего метода)? Самый простой - это то, что сказал ataddeini, если сможете. – NSGaga

ответ

3

Я бы поменял GetFoo и GetBar, чтобы просто быть Get, и сделать MesReportingDal общим тоже.

Так что я думаю, что вы в конечном итоге с чем-то вроде этого:

private static List<T> GetObjectList(DateTime mostRecentProcessedReadTime) 
{ 
    using (var data = new MesReportingDal<T>()) 
    { 
     return data.Get(mostRecentProcessedReadTime);   
    } 
} 

Кстати, имея using утверждение также требует, чтобы MesReportingDal реализует IDisposable, в противном случае вы получите следующее сообщение об ошибке компиляции:

«MesReportingDal»: тип, используемый в используемой заявке, должен быть неявно конвертируемым в «System.IDisposable»

UPDATE

Так что, подумав об этом еще и прочитав ваши отзывы, вам нужно извлечь интерфейс репозитория и вернуть его обратно на заводский метод. Это позволит вам сохранить единый data.Get(...) вызов, но с различными реализациями на основе T

public interface IRepository<T> : IDisposable 
{ 
    IList<T> Get(DateTime mostRecentRead); 
} 

public class FooRepo : IRepository<Foo> 
{ 
    public IList<Foo> Get(DateTime mostRecentRead) 
    { 
     // Foo Implementation 
    } 
} 

public class BarRepo : IRepository<Bar> 
{ 
    public IList<Bar> Get(DateTime mostRecentRead) 
    { 
     // Bar Implemenation 
    } 
} 

Ваш завод мог бы выглядеть примерно так

public class RepositoryFactory 
{ 
    public static IRepository<T> CreateRepository<T>() 
    { 
     IRepository<T> repo = null; 
     Type forType = typeof(T); 

     if (forType == typeof(Foo)) 
     { 
      repo = new FooRepo() as IRepository<T>; 
     } 
     else if (forType == typeof(Bar)) 
     { 
      repo = new BarRepo() as IRepository<T>; 
     } 

     return repo; 
    } 
} 

И это позволит вам сохранить ваш исходный код блок чистый

private static IList<T> GetObjectList(DateTime mostRecentProcessedReadTime) 
{ 
    using (var data = RepositoryFactory.CreateRepository<T>()) 
    { 
     return data.Get(mostRecentProcessedReadTime); 
    } 
} 

Надеюсь, что это поможет.

+0

Я не знаю, что это сработает, и может быть, потому что я был не очень ясен. Метод data.Get() имеет разные реализации, основанные на типе. Алгоритм в Get() отличается. –

+0

@BobHorn Справа, хорошо. Думая об этом больше, я продолжаю возвращаться к интерфейсу репозитория и фабрике. Я попытаюсь кратко обновить пример. – ataddeini

+0

Спасибо. Хотя это заставляет логику if где-то еще, она действительно сохраняет код потребления чистым. Я надеялся избежать логики *, если вообще, но это решение по крайней мере удерживает его на фабрике. Я думаю, что мой единственный вариант - это отражение, но теперь это может работать. –