动态可交换数据访问层

And*_*sch 3 c# oop reflection polymorphism wcf

我正在编写一个数据驱动的WPF客户端。客户端通常会从WCF服务中提取数据,该服务会查询SQL数据库,但是我想选择直接从SQL或其他任意数据源中提取数据的选项。

我已经提出了这个设计,并且想听听您对它是否是最佳设计的看法。

首先,我们有一些要从SQL中提取的数据对象。

// The Data Object with a single property
public class Customer
{
    private string m_Name = string.Empty;

    public string Name 
    {
        get { return m_Name; }
        set { m_Name = value;}
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,我计划使用所有数据访问层都应实现的接口。假设还可以使用一个抽象类。有什么想法吗?

// The interface with a single method
interface ICustomerFacade
{
    List<Customer> GetAll();
}
Run Code Online (Sandbox Code Playgroud)

可以创建一个SQL实现。

// Sql Implementation
public class SqlCustomrFacade : ICustomerFacade
{
    public List<Customer> GetAll()
    {
        // Query SQL db and return something useful
        // ...

        return new List<Customer>();
    }
}
Run Code Online (Sandbox Code Playgroud)

我们还可以创建WCF实现。WCF的问题在于它不使用相同的数据对象。它会创建自己的本地版本,因此我们将不得不以某种方式复制详细信息。我想可以使用反射来复制相似字段的值。有什么想法吗?

// Wcf Implementation
public class WcfCustomrFacade : ICustomerFacade
{
    public List<Customer> GetAll()
    {
        // Get date from the Wcf Service (not defined here)
        List<WcfService.Customer> wcfCustomers = wcfService.GetAllCustomers();

        // The list we're going to return
        List<Customer> customers = new List<Customer>();

        // This is horrible
        foreach(WcfService.Customer wcfCustomer in wcfCustomers)
        {
            Customer customer = new Customer();
            customer.Name = wcfCustomer.Name;
            customers.Add(customer);
        }

        return customers;
    }
}
Run Code Online (Sandbox Code Playgroud)

我还计划使用工厂来决定使用哪个外观。

// Factory pattern
public class FacadeFactory()
{
    public static ICustomerFacade CreateCustomerFacade()
    {
        // Determine the facade to use
        if (ConfigurationManager.AppSettings["DAL"] == "Sql")
            return new SqlCustomrFacade();
        else
            return new WcfCustomrFacade();
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是通常使用DAL的方式。

// Test application
public class MyApp
{
    public static void Main()
    {
        ICustomerFacade cf = FacadeFactory.CreateCustomerFacade();
        cf.GetAll();
    }
}
Run Code Online (Sandbox Code Playgroud)

感谢您的想法和时间。

Ran*_*pho 5

您可以从一个非常灵活的软件方法开始。您已经遇到了方法上的主要问题:数据提供者合同(ICustomerFacade)必须指定所有实现者都使用的数据对象。SQL和WCF数据提供程序都必须返回相同的数据对象。

您标记为“这太可怕了”的那部分?其实并没有那么糟糕。您要迭代两次,是的,但是这样做是为了提供更强大,更灵活的软件体系结构。性能不会那么差(除非您要遍历列表中的许多项目),并且您的系统将能够在调用Web服务和直接调用SQL Server之间进行切换(通常,这是否是个好主意)随意。

消除重复的一件事是让数据协定依赖于数据对象的抽象。例如,他们会返回ICustomer而不是Customer。然后,您的SQL Server对象和WCF数据对象可以完全是不同的对象,只要它们实现了ICustomer等接口即可。

其他建议:

  • 您应该考虑返回IList(或什至IEnumerable),而不是List考虑使用集合返回方法。
  • 您的工厂模式是一个良好的开端,但工厂则是2000年代。:)您可能要考虑采用完整的依赖关系注入路径;我建议在Microsoft Enterprise Library中使用 Unity 。