基于类型调用 DAL 方法
Posted
技术标签:
【中文标题】基于类型调用 DAL 方法【英文标题】:Call DAL Method Based on Type 【发布时间】:2012-04-20 13:48:38 【问题描述】:我正在开发一个应用程序,我需要根据调用类的泛型类型调用两种数据方法之一。例如,如果 T 是 Foo 类型,我将调用 data.GetFoo():
private static List<T> GetObjectList(DateTime mostRecentProcessedReadTime)
using (MesReportingDal data = new MesReportingDal())
return data.GetFoo(mostRecentProcessedReadTime); // Notice GetFoo()
如果 T 是 Bar 类型,我会调用 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 语句?
编辑 - 这就是类型的样子
public partial class Foo1 : IDataEntity
public partial class Foo2 : IDataEntity
public partial class Bar1 : IDataEntity
public partial class Bar2 : IDataEntity
这些 Foos 和 Bars 是用于 Linq-to-SQL 的 DBML 项。
【问题讨论】:
您是否可以控制“T”类 - 它们是否可以更改,您是否有基本接口/类等。 如果您不想更改 Foo*、Bar* 并且它必须是 GetFoo、GetBar - 而不是 ataddeini 建议的 Get()(如果我理解正确?)。您打算如何“调用”GetObjectList()?你在定义例如Foo, Bar 在调用之前(所以你有一个类型的变量) - 或者你想以某种高度通用的方式调用它(使用另一个通用方法中的 T )?如果可以的话,最简单的是 ataddeini 所说的。static
的使用已经让我很担心了。你能解释一下你认为这违反了OCP吗?没有上下文,很难说。
@NSGaga 我也许可以按照 ataddeini 所说的去做。我还没有时间。我很快就会检查出来。
@jeyoung 它违反了OCP,因为我们必须记住if语句并为每个新类型添加它。
【参考方案1】:
我会将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':在 using 语句中使用的类型必须隐式转换为 'System.IDisposable'
更新
因此,在考虑了更多并阅读了您的反馈之后,您可以选择提取存储库接口并将创建推回工厂方法。这将允许您维护单个 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);
希望对您有所帮助。
【讨论】:
我不知道这会起作用,可能是因为我不是很清楚。 data.Get() 方法根据类型有不同的实现。 Get() 中的算法不同。 @BobHorn 对,好的。考虑更多这一点,我不断回到存储库接口和工厂。我会尽快用一个例子来更新。 谢谢。虽然这将 if 逻辑推到了其他地方,但它确实使消费代码保持干净。我希望完全避免 if 逻辑,但这个解决方案至少将其保留在工厂内。我认为我唯一的其他选择是反射,但这现在可以工作。 仅供参考,此行最终返回 null:repo = new FooRepo() as IRepository以上是关于基于类型调用 DAL 方法的主要内容,如果未能解决你的问题,请参考以下文章