Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 使用存储库模式和DI在SQL和XML ASP.NETMVC之间切换_Asp.net Mvc_Dependency Injection_Repository Pattern - Fatal编程技术网

Asp.net mvc 使用存储库模式和DI在SQL和XML ASP.NETMVC之间切换

Asp.net mvc 使用存储库模式和DI在SQL和XML ASP.NETMVC之间切换,asp.net-mvc,dependency-injection,repository-pattern,Asp.net Mvc,Dependency Injection,Repository Pattern,我有XMLProductRepository和SQLProductRepository。现在我如何在它们之间动态切换。我是DI的新手。所以在谷歌上搜索同样的内容,发现了一个链接,上面有一些讨论。但仍然不了解存储库将在什么基础上更改,以及如何更改。这是密码 public interface IProductRepository { IEnumerable<Product> GetAll(); Product Get(int id); Product Add(Pr

我有XMLProductRepository和SQLProductRepository。现在我如何在它们之间动态切换。我是DI的新手。所以在谷歌上搜索同样的内容,发现了一个链接,上面有一些讨论。但仍然不了解存储库将在什么基础上更改,以及如何更改。这是密码

public interface IProductRepository
{
    IEnumerable<Product> GetAll();
    Product Get(int id);
    Product Add(Product item);
    void Remove(int id);
    bool Update(Product item);
}

public class XMLProductRepository : IProductRepository
{

    public XMLProductRepository() {}
    public IEnumerable<Product> GetAll() {}
    public Product Get(int id) {}
    public Product Add(Product item) {}
    public void Remove(int id) {}
    public bool Update(Product item) {}
}

public class SQLProductRepository : IProductRepository
{
    public SQLProductRepository() {}
    public IEnumerable<Product> GetAll() {}
    public Product Get(int id) {}
    public Product Add(Product item) {}
    public void Remove(int id) {}
    public bool Update(Product item) {}
} 

Unity.Mvc3 is using as Di

public static class Bootstrapper
{
    public static void Initialise()
    {
        var container = BuildUnityContainer();
        DependencyResolver.SetResolver(new UnityDependencyResolver(container));
    }

    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer();
        //Register the repository
        container.RegisterType<IProductRepository, SQLProductRepository>();
        return container;
    }
}

protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        AuthConfig.RegisterAuth();
        Bootstrapper.Initialise();

    }

public class HomeController : Controller
{
    private readonly IProductRepository productRepository;

    public HomeController(IProductRepository productRepository)
    {
        this.productRepository = productRepository;
    }
公共接口存储库
{
IEnumerable GetAll();
产品获取(int-id);
产品添加(产品项);
无效删除(int-id);
bool更新(产品项);
}
公共类XMLProductRepository:IPProductRepository
{
公共XMLProductRepository(){}
公共IEnumerable GetAll(){}
公共产品Get(int-id){}
公共产品添加(产品项){}
公共无效删除(int-id){}
公共布尔更新(产品项){}
}
公共类SQLProductRepository:IPProductRepository
{
公共SQLProductRepository(){}
公共IEnumerable GetAll(){}
公共产品Get(int-id){}
公共产品添加(产品项){}
公共无效删除(int-id){}
公共布尔更新(产品项){}
} 
Unity.Mvc3用作Di
公共静态类引导程序
{
公共静态无效初始化()
{
var container=BuildUnityContainer();
SetResolver(新UnitedDependencyResolver(容器));
}
私有静态IUnityContainer BuildUnityContainer()
{
var container=new UnityContainer();
//注册存储库
container.RegisterType();
返回容器;
}
}
受保护的无效应用程序\u Start()
{
RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
Bootstrapper.Initialise();
}
公共类HomeController:控制器
{
私有只读IPProductRepository productRepository;
公共HomeController(IPProductRepository productRepository)
{
this.productRepository=productRepository;
}
我理解动态地
SQLProductRepository
实例正在注入控制器的代码。所以我的问题是如何注入
XMLProductRepository

我想设计这样一个基于url依赖的东西将被注入。
如何实现它。正在寻找指导原则。谢谢

一个可能的解决方案是注入
IPProductRepositoryFactory
,而不是
IPProductRepository
本身。它将如下所示:

interface IProductRepositoryFactory
{
    IProductRepository GetRepository(string url);
}
public class HomeController : Controller
{
    private readonly IProductRepositoryFactory productRepositoryFactory;

    public HomeController(IProductRepositoryFactory productRepositoryFactory)
    {
        this.productRepositoryFactory = productRepositoryFactory;
    }
}
然后您的
家庭控制器将如下所示:

interface IProductRepositoryFactory
{
    IProductRepository GetRepository(string url);
}
public class HomeController : Controller
{
    private readonly IProductRepositoryFactory productRepositoryFactory;

    public HomeController(IProductRepositoryFactory productRepositoryFactory)
    {
        this.productRepositoryFactory = productRepositoryFactory;
    }
}
这样,您将能够在运行时的控制器操作中获得所需的
ipProductRepository
实现—您所需的只是在
ipProductRepositoryFactory.GetRepository(url)
方法中实现所需的逻辑

下面是一个控制器操作示例(请注意,以这种方式获取当前请求URL会降低此方法的可测试性):

UPD:以下是
IPProductRepositoryFactory
的示例实现。只需实现您自己的决策逻辑,根据URL返回
IPProductRepository
的适当实例即可:

public class ProductRepositoryFactory : IProductRepositoryFactory
{
    public IProductRepository GetRepository(string url)
    {
        if (url.Contains("xml")) { return new XMLProductRepository(); }
        if (url.Contains("sql")) { return new SQLProductRepository(); }
        throw new ArgumentException("url");

    }
}

我不知道代码是从哪里来的,但是您展示的
IProductRepository
的两个实现有两个目的

  • SQLProductRepository
    将从数据库中读取和写入数据
  • XMLProductRepository
    可以读取XML,也可以编写文件
在单元测试中运行代码时,通常不希望连接到数据库,但有时确实希望在单元测试中使用数据。这就是XML存储库的用武之地。在XML文件中准备一个可以提交到版本控制的数据集,然后注入请求接口的另一个实现,即读取这是XML文件,您不再需要数据库了

这就是为什么您将DI容器配置为注入
SQLProductRepository
,而在单元测试中,当应用程序请求
IPProductRepository
时,您或DI容器将提供
XMLProductRepository

现在,如果您说您的控制器,您的业务逻辑,是基于URI为一个特定请求选择
SQLProductRepository
,为另一个请求选择
XMLProductRepository
,那么使用
IProductRepository
是错误的。这是一个不应该使用DI容器解决的问题

引入两个新接口,并将其应用于存储库:

public interface ISqlProductRepository : IProductRepository
{
}

public interface IXmlProductRepository : IProductRepository
{
}

SQLProductRepository : ISqlProductRepository
XMLProductRepository : IXmlProductRepository
并登记及注射:

// Application startup
container.RegisterType<ISqlProductRepository, SQLProductRepository>();
container.RegisterType<IXmlProductRepository, XMLProductRepository>();

// Controller
private readonly ISqlProductRepository _sqlProductRepository;
private readonly IXmlProductRepository _xmlProductRepository;

public HomeController(ISqlProductRepository sqlProductRepository, IXmlProductRepository xmlProductRepository)
{
    _sqlProductRepository = sqlProductRepository;
    _xmlProductRepository = xmlProductRepository;
}

public ActionResult SqlMethod1()
{
    // use _sqlProductRepository
}

public ActionResult XmlMethod2()
{
    // use _xmlProductRepository
}
//应用程序启动
container.RegisterType();
container.RegisterType();
//控制器
私有只读ISqlProductRepository\u sqlProductRepository;
专用只读IXmlProductRepository xmlProductRepository;
公共HomeController(ISqlProductRepository sqlProductRepository、IXmlProductRepository xmlProductRepository)
{
_sqlProductRepository=sqlProductRepository;
_xmlProductRepository=xmlProductRepository;
}
公共操作结果SqlMethod1()
{
//使用sqlProductRepository
}
公共行动结果XmlMethod2()
{
//使用xmlProductRepository
}
当然,现在您不能再为
SQLProductRepository
注入
XMLProductRepository
,但这是一个使用模拟很容易解决的问题


不管怎么说,基于您当前的一连串问题,您正在尝试学习有关单元测试和依赖项注入的知识。请拿起一本像样的书,停止将博客文章中的内容捆绑在一起,因为这些文章几乎无法解释您需要知道的一切。

为什么您需要在这两个存储库之间动态切换?使用@Steven.Th是完全不是什么依赖