简体   繁体   English

接口对象实例化和n层封装

[英]Interface object instantiation and n-layer encapsulation

We are bulding a system that we want the final implementation do "hide" the data access layer (so that we can change it in the future). 我们正在建立一个我们希望最终实现“隐藏”数据访问层的系统(以便将来可以更改它)。

So the idea is that the application code will call an interface that will be implemented by Database access objects. 因此,想法是应用程序代码将调用将由数据库访问对象实现的接口。 So we have the interface class: 因此,我们有了接口类:

public interface DatabaseInterface

    {
        void Create(DataObject obj);
    }

Then we have the class that implements the interface: 然后,我们有了实现该接口的类:

public class DatabaseAccess : DatabaseInterface

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

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

Together will all this, we have the DataObject class: 所有这些在一起,我们将得到DataObject类:

public class DataObject
{
     integer Data1;
     string  Data2;
}

OUr problems sits on the main application, as I don´t know what is the DatabaseInterface implementation: 我们的问题在于主应用程序,因为我不知道什么是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);
    }

How do I call the implemented method without knowing which class did it ? 如何在不知道是哪个类的情况下调用实现的方法? Surely I´m missing something on my design. 当然,我的设计中缺少一些东西。

We REALLY wanna make the application fully independent from the code below. 我们真的想使应用程序完全独立于下面的代码。

[EDIT 1] [编辑1]

These implementations reside in different class libraries. 这些实现位于不同的类库中。 So I have the following: App project DatabaseInterface project DatabaseAccess project DataObject project 因此,我有以下内容:App项目DatabaseInterface项目DatabaseAccess项目DataObject项目

what you are missing is a "factory" class that builds instances for outside world based on parameters or configuration settings it receives (if they want to have the outside world influencing its behavior) or make their own decisions, ie they will create the instances of either type A or B based on their internal logic that cannot be changed from the outside. 您缺少的是一个“工厂”类,它根据收到的参数或配置设置(如果他们想让外界影响其行为)或做出自己的决定为外界构建实例,即他们将创建以下实例根据内部逻辑无法从外部更改A或B类型。 In the code below you will see the DatabaseFactory which is what you were missing. 在下面的代码中,您将看到缺少的DatabaseFactory。 Also, note the private/public/internal modifiers which are important to make sure you expose what is needed and not more than you need (making all classes public creates confusions to those who want to use your library) 另外,请注意private / public / internal修饰符,这些修饰符对于确保公开需要的内容而不是超出所需的内容非常重要(将所有类公开化会使想要使用您的库的人感到困惑)

Here is the code 这是代码

// 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);
}

You could make a class that would create the correct DAL object. 您可以创建一个可以创建正确的DAL对象的类。 Something like this: 像这样:

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

Then, to make a DAL object: 然后,制作一个DAL对象:

var dbAccess = RepositoryFactory.MakeDAL();

Depending on how much separation you want between the app and the database access, you would put the interfaces, the interface implementations, and the factory class in separate assemblies, or put some in one assembly and some in another. 根据您希望在应用程序和数据库访问之间实现多少分隔,您可以将接口,接口实现和工厂类放在单独的程序集中,或者将一个放在一个程序集中,另一个放在另一个程序集中。 It really depends on what you mean when you say "fully independent from the source code". 这实际上取决于您说“完全独立于源代码”的含义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM