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

时间:2013-08-26 20:27:50

标签: c# reflection interface factories

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

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

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

OUr问题存在于主应用程序中,因为我不知道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]

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

2 个答案:

答案 0 :(得分:3)

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

这是代码

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

答案 1 :(得分:0)

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

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

然后,制作一个DAL对象:

var dbAccess = RepositoryFactory.MakeDAL();

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