0

我们正在构建一个系统,我们希望最终实现“隐藏”数据访问层(以便我们将来可以更改它)。

所以想法是应用程序代码将调用一个接口,该接口将由数据库访问对象实现。所以我们有接口类:

public interface DatabaseInterface

    {
        void Create(DataObject obj);
    }

然后我们有实现接口的类:

public class DatabaseAccess : DatabaseInterface

    { 
        void Create(DataObject obj)
        { 
            Entity dbContext = new Entity();

            dbContext.Data.Add (obj);
            dbContext.SaveChanged();
       }
    }

将这一切加在一起,我们就有了 DataObject 类:

public class DataObject
{
     integer Data1;
     string  Data2;
}

我们的问题出在主应用程序上,因为我不知道 DatabaseInterface 实现是什么:

public class CreateElementOnDatabase

    {
         DataObject myObj = new DataObject();
         myObj.Data1 = 10;
         myObj.Data2 = "Test String";

         var dbAccess = new DatabaseInterface() <=== I know this is not possible, but don´t know what to do!!!!

         dbAccess.Create (myObj);
    }

如何在不知道是哪个类的情况下调用已实现的方法?我肯定在我的设计中遗漏了一些东西。

我们真的想让应用程序完全独立于下面的代码。

[编辑 1]

这些实现驻留在不同的类库中。所以我有以下内容: App 项目 DatabaseInterface 项目 DatabaseAccess 项目 DataObject 项目

4

2 回答 2

3

你缺少的是一个“工厂”类,它根据它接收到的参数或配置设置为外部世界构建实例(如果他们想让外部世界影响其行为)或做出自己的决定,即他们将创建实例类型 A 或 B 基于其内部逻辑,无法从外部更改。在下面的代码中,您将看到您缺少的 DatabaseFactory。另外,请注意 private/public/internal 修饰符,这些修饰符对于确保您公开所需内容而不是超出您的需要很重要(将所有类公开会给想要使用您的库的人造成混乱)

这是代码

// interfaces must be public - this is the "contract" with the outside world / assemblies
public interface IDatabase
{
    void Create(DataObject obj);
}

// classes that implement interfaces should be internal - outside world don't know about them
internal class SQLDatabase : IDatabase
{
    // internal on constructor helps you to make sure you are the only one 
    // that can create such an instance
    internal SQLDatabase()
    {
    }
    void Create(DataObject obj)
    {
        Entity dbContext = new Entity();
        dbContext.Data.Add(obj);
        dbContext.SaveChanged();
    }
}
internal class OracleDatabase : IDatabase
{
    internal OracleDatabase()
    {
    }
    void Create(DataObject obj)
    {
        //oracle creation method
    }
}

public class DataObject
{
    int Data1;
    string Data2;
}

// this is the factory class that creates the instances for you (ourside world)
public class DatabaseFactory
{
    // you can use either params or ideally app.config keys
    public IDatabase CreateInstace()
    {
        if (ConfigSetting == "SQL")
        {
            return new SQLDatabase();
        }
        else if (ConfigSetting == "Oracle")
        {
            return new OracleDatabase();
        }
        else throw new System.Exception ("invalid configuration setting key");
    }
}

// this is in external assembly:
public class CreateElementOnDatabase
{
     DataObject myObj = new DataObject();
     myObj.Data1 = 10;
     myObj.Data2 = "Test String";

    // you only work with public interfaces
    // and the factory creates the instances for you ...
     IDatabase db = DatabaseFactory.CreateInstace();
     db.Create(myObj);
}
于 2013-08-26T21:01:31.877 回答
0

您可以创建一个可以创建正确 DAL 对象的类。像这样的东西:

public class RepositoryFactory {
    public static DatabaseInterface MakeDAL() {
        return new DatabaseAccess();
    }
}

然后,制作一个 DAL 对象:

var dbAccess = RepositoryFactory.MakeDAL();

根据您希望在应用程序和数据库访问之间分离多少,您可以将接口、接口实现和工厂类放在单独的程序集中,或者将一些放在一个程序集中,而将一些放在另一个程序集中。当您说“完全独立于源代码”时,这实际上取决于您的意思。

于 2013-08-26T20:47:16.953 回答