关于在存储库模式中使用构造函数的困惑

时间:2018-07-18 12:04:33

标签: c# model-view-controller

我是C#的新手,我已经了解了构造函数,并且我了解到我们使用它们的原因是我们可以在构造时分配我们想要的任何东西,但是我很难理解的是IRepository学生喜欢:

{
    "DatagreenhouseRecuperado": [
        {
            "_id": "2018-03-24T01: 18: 18.619Z",
            "measurements": [
                {
                    
                    "sensor": {
                        "_id": "5b4de5121852a4b3ae632db5",
                        "name": "var_ContadorRiego",
                        "type": "resources",
                        "place": "interior",
                        "img": "assets / img / temp.png",
                        "user": "5b10176084195a07f63c942a",
                        "greenhouse": "5b1027896933440c030f8a6b",
"attrName": "var_ContadorRiego",
                    "attrValue": "0",
                        "__v": 0
                    }
                },
                {
                    "attrName": "var_PotActBio",
                    "attrValue": "8.384025",
                    "sensor": {
                        "_id": "5b4de5121852a4b3ae632db3",
                        "name": "var_PotActBio",
                        "type": "resources",
                        "place": "interior",
                        "img": "assets / img / temp.png",
                        "user": "5b10176084195a07f63c942a",
                        "greenhouse": "5b1027896933440c030f8a6b",
"attrName": "var_ContadorRiego",
                    "attrValue": "0",
                        "__v": 0
                    }
                },
                {
                    "attrName": "var_PotActInv",
                    "attrValue": "0.130222",
                    "sensor": {
                        "_id": "5b4de5121852a4b3ae632db1",
                        "name": "var_PotActInv",
                        "type": "resources",
                        "place": "interior",
                        "img": "assets / img / temp.png",
                        "user": "5b10176084195a07f63c942a",
                        "greenhouse": "5b1027896933440c030f8a6b",
"attrName": "var_ContadorRiego",
                    "attrValue": "0",
                        "__v": 0
                    }
                }

我在StudentRepository中实现了它

    public  interface IStudentRepository
    {

        object getAll();
    }

在我的homeController中,我可以执行以下操作:

     public class StudentRepository:IStudentRepository
    {
       public testDBEntities DB = new testDBEntities();
        public object getAll()
        {
            var reslt = (from s in DB.Students
                     select new StudentViewModel
                     {
                         Name = s.Name,
                         Id=s.Id
                     });

            return reslt;
        }
    }

那我为什么要有一个构造函数呢?

    IStudentRepository _repository=new StudentRepository();   
    public JsonResult Index()
    {
       var m= _repository.getAll();
       return Json(m,JsonRequestBehavior.AllowGet);
    }

对不起,如果我的问题很简单,但是我找不到正确的答案,请先感谢

2 个答案:

答案 0 :(得分:4)

单一责任原则

第一个优点是您的HomeController不必担心创建StudentRepository对象。其他人已经实例化它,它是从数据库,文件或用户输入等生成的。这很棒,因为您的控制器可以专注于其实际工作,而不是如何实例化另一个对象。 Single Responsibility Principle上的距离越来越近。

依赖注入

然后,要利用第二个优点,构造函数应接收接口而不是类。称为Dependency Injection

如果以后由于某种原因而决定以任何方式更改StudentRepository类,只要您仍然实现该接口,就不必对控制器进行更改。

因此您的最终代码可能如下:

class HomeController
{
    private IStudentRepository _repository;
    public HomeController(IStudentRepository _repository)
    {
        //We don't know who instanciated the repo, but we don't care
        this._repository = _repository;
    }

    public JsonResult Index()
    {
        //We only know about the repo that it implements IStudentRepository
        //So we know we can call this method without a risk.
        var m= _repository.getAll();
        return Json(m,JsonRequestBehavior.AllowGet);
    }
}

更改时

为说明更改,假设您首先要测试存储库,但没有正确的数据库连接。因此,您决定使用文件,您的课程将像这样:

public class TestStudentRepository : IStudentRepository
{
    private string MyDatabaseFilePath;

    public object getAll()
    {
        //Load everything from my text file
    }
}

好的,这行得通。现在,我们与数据库建立了连接,但是在使用getAll()方法之前,该连接需要一些步骤。使用您的解决方案,您将必须在HomeController中执行初始化步骤。

现在有了这种模式,您可以执行以下操作:

public class StudentRepository : IStudentRepository
{
    private string _connectionString;

    public DatabaseStudentRepository(string ConnectionString)
    {
        _connectionString = ConnectionString;
    }

    public object getAll()
    {
        //Load everything from my text file
    }
}

然后,正是对象的角色使用控制器来确保它正确地实例化了您的对象。您的控制器没有任何变化。

工厂模式

最后一步是为您的StudentRepository创建一个工厂。维护适当的回购是工厂的职责:

public static class StudentRepositoryFactory
{
    public static IStudentRepository InstanciateRepo(bool FromDatabase)
    {
        if (FromDatabase)
        {
            return new DatabaseStudentFactory("ConnectionString To my server");
        }
        else
        {
            return new TestStudentRepository();
        }
    }
}

现在,无论您需要以何种方式初始化仓库,这都是工厂的职责。使用存储库中的一种方法getAll()是Controller的职责。

答案 1 :(得分:1)

我认为您的构造函数不正确。它一定喜欢

IStudentRepository _repository
public HomeController(IStudentRepository _repository)
{
     this._repository = _repository;
}

实际上,最好在构造函数中传递IStudentRepository以尊重pattern dependency injection

想象您要通过单元测试来测试控制器。因此,您要创建虚假数据。如果您在控制器内创建新的StudentRepository,如何对其进行测试?。

但是如果您通过构造函数,例如:

public class FakeStudentRepository : IStudentRepository 
{
     //return fake data
}

通过一些配置,第三个库``依赖注入''会将您的假仓库传递给控制器​​,您可以对其进行测试