2

将 Ninject 与 ASP.NET MVC 一起使用时,抽象出 3rd 方依赖项的最佳方法是什么?

通常,我会这样做:

public interface IProductRepository
{
    IEnumerable<Product> GetProducts();
}

public class ProductRespository : IProductRepository
{
    public IEnumerable<Product> GetProducts()
    {
        ...
    }
}

然后在控制器中:

public class ProductController : Controller
{
    private IProductRepository repository;

    public ProductController(IProductRepository repository)
    {
        this.repository = repository;
    }

    ...
}

然后我使用 Ninject 将固体 ProductRepository 自动注入控制器。

但是,如果依赖项是第 3 方,我该怎么做?例如,我正在使用FlickrNet

public class ProductController : Controller
{
    private Flickr flickr;

    ...
}

我希望能够将Flickr对象抽象到一个接口中,以便我可以使用依赖注入并使其更容易进行单元测试。我知道我可以创建一个“服务”类型的接口,然后实现一个基于包装 Flickr 对象的类。

但是我必须在接口中定义一个与 Flickr 对象的每个成员相对应的成员,然后将每个成员映射到包装器对象中。Flickr 对象中有很多很多的成员。

有没有更好的方法来处理这个问题?我的主要目标是在单元测试中轻松模拟 Flickr 依赖项。

4

4 回答 4

3

将我的评论升级为答案。

这不是 DI 的问题,而是一般的架构问题。您可以将控制器声明为抽象层,也可以在实现自定义接口的 flickr 组件周围定义一个包装器。如果您的 3rd 方组件上的方法使用更多的 3rd 方类,则您也需要将它们抽象出来,依此类推,直到您只剩下原始值或更多围绕 3rd 方代码的包装器。根据该组件的复杂性,这可能意味着大量的映射和包装。

于 2012-08-09T09:54:15.760 回答
2

我认为包装器是正确的方法。您不必公开 3rd 方对象的每个成员 - 只需公开您需要的那些。不同的情况下使用不同的接口,包装器解决方案变得更加漂亮。

于 2012-08-09T08:03:46.933 回答
1

我知道这篇文章不是关于单元测试的,但它提供的解决方案顺便也适用于基于模拟的单元测试。

http://goodcoffeegoodcode.blogspot.com/2011_04_01_archive.html

基本上,正如@Brian Dishaw 建议的那样,您需要从 FlickrNet 类中提取接口并将它们注入到您的类中。

于 2012-08-09T03:53:56.663 回答
1

The only purpose would be if you abstract away flickr .NET into a higher abstraction layer. For instance

interface IAlbumViewer
{
   IEnumerable<IImage> GetImages();
}

interface IPictureUploader
{
   string Upload(string filename, Stream image)
}

That is, create interfaces/methods that are specific for your usecases contra generic flickr interfaces. You would also benefit from that since it makes it a lot easier to add support for other image services.

于 2012-08-09T14:23:53.650 回答