2

我正在开发一个应用程序,我需要根据调用类的泛型类型调用两种数据方法之一。例如,如果 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 项。

4

1 回答 1

3

我会改变GetFooGetBar成为Get,并做出MesReportingDal一个通用的。

所以我认为你最终会得到这样的结果:

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

顺便说一句,拥有该using语句还需要MesReportingDalimplements 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);
    }
}

希望有帮助。

于 2012-04-20T13:56:15.150 回答