依赖注入中接口的C#名称空间

依赖注入中接口的C#名称空间,c#,dependency-injection,interface,namespaces,dependencies,C#,Dependency Injection,Interface,Namespaces,Dependencies,我想在C#中使用依赖注入模式,并且我想在名称空间中尽可能地分离逻辑 问题: 所使用类的接口应该在哪个命名空间中 问题的动机 首先让我们做一些“正常”的案例。作为第二部分解释的基础的书箱。然后,“现实生活”案例,这就产生了问题 书柜 让我们假设编码者是Alice,并且她使用Alice作为供应商在名称空间中作为顶级名称,以避免与其他编码者发生冲突。在本例中,我们假设世界上没有其他Alice 假设她创建了3个名称空间: 爱丽丝.入侵者——一款通过商店提供应用内购买的游戏 Alice.Shop-一个可

我想在C#中使用
依赖注入
模式,并且我想在名称空间中尽可能地分离逻辑

问题: 所使用类的
接口
应该在哪个命名空间中

问题的动机 首先让我们做一些“正常”的案例。作为第二部分解释的基础的书箱。然后,“现实生活”案例,这就产生了问题

书柜 让我们假设编码者是Alice,并且她使用
Alice
作为供应商在名称空间中作为顶级名称,以避免与其他编码者发生冲突。在本例中,我们假设世界上没有其他Alice

假设她创建了3个名称空间:

  • 爱丽丝.入侵者
    ——一款通过商店提供应用内购买的游戏
  • Alice.Shop
    -一个可重复使用的商店,用于多种游戏
  • Alice.Injector
    -可重用的服务管理器
让我们假设
Shop
项目有一个名为
IShopService
接口,该接口提供了一个方法
Show()

让我们假设,
入侵者
有某种控制器,在某些用户操作中,它想要打开商店

让我们假设服务,如
商店
,是由
入侵者的控制器通过
服务管理器
获得的

艾丽斯,注射器
Alice.Injector
本身是一个没有依赖关系的独立项目,因此它不使用“using”关键字:

爱丽丝,去商店
Alice.Shop
也是一个独立的项目,它(除使用服务的情况外)不知道喷油器的存在。只是一家商店而已

由于Alice认为Bob将来可能会做得更好,因此她准备将类注入依赖项,将
shop
分离为接口
IShop
,然后实现,如下本文所示:

为了实现这一点,Alice将使商店成为一种与
Alice.ServiceManager
兼容的服务类型,因此Alice决定将
IShop
重命名为
IShopService
,它将是一种
IService

using Alice.Injector

namespace Alice.Shop
{
    public interface IShopService : IService
    {
        public void Show();
    }

    public class Shop : IShopService
    {
        public void Show()
        {
            // Here Alice puts all the code to open the shop up.
        }
    }
}
爱丽丝,入侵者 最后,爱丽丝编写了游戏代码。
Alice.investors
的代码通过
ServiceManager
获得一个
Shop
(以服务的形式),因此它是干净的代码

using Alice.Injector
using Alice.Shop

namespace Alice.Invaders
{
    public class DefaultController
    {
        void OnShopClick()
        {
            IShopService shop = ServiceManager.Get( "Shop" ) as IShopService;
            shop.Show();
        }
    }
}
到目前为止,一切都很顺利

真实案例 所以现在。。。鲍勃(大家都知道,他是爱丽丝的好朋友,很好奇他们今天不谈论发送加密信息),开了一家超级不错的商店,比爱丽丝开的那家店还要好。鲍勃从头做起

因此Bob实现了与Alice的injector兼容的商店(Bob也使用
Alice.injector
在他的项目中注入其他东西)

所以。。。这就是奇怪的情况

  • Bob.Shop
    接口的名称空间
    -如果Bob按照上面显示的方式在
    Bob.Shop
    名称空间内购物,那么Alice必须编辑她的代码以引用
    Bob.Shop
    ,以获得
    IShopService
    接口(她必须更改代码中的依赖项,因为应该使用依赖项注入器来摆脱更改代码中的依赖项)
  • 接口没有名称空间-如果Alice和Bob都在全局名称空间中设置了
    IShopService
    ,那么它也很难看,因为那里有很多东西可能会冲突
  • Alice.Shop
    接口的名称空间
    -如果Bob利用常识说“我想做的是创建一个与Alice的商店兼容的商店,那么我应该实现她的接口”,那么Bob的代码很可能如下所示:
Bob的代码使用
Alice.Shop
向后命名空间兼容性:

namespace Bob.Shop
{
    public class Shop : Alice.Shop.IShopService
    {
        public void Show()
        {
            // Here Bob does a brand new shop from scratch,
            // which borrows Alice's interface.
        }
    }
}
在这种情况下,似乎一切就绪:

  • Bob可以创建实现Alice.Shop.IShopService的
    Bob.Shop.Shop
  • Alice不需要更改一行代码
  • Alice.Injector.ServiceManager
    能够在为
    Bob.Shop.Shop
    提供服务时提供另一个
    iSeries设备
问题 这里仍然有一个依赖关系:

Alice.investors
正在将
Alice.Injector.IService
强制转换为
Alice.Shop.IShopService
,以便能够调用
Show()
方法。如果不执行该强制转换,则无法“显示商店”

因此,在最后,您将“依赖”该类型转换,因此“某人”需要向您提供接口定义

如果最初的shop不是Alice写的,而是Charlie写的,那么为了使用
Bob.shop
,还必须下载并保存
Charlie.shop
项目的副本将是“丑陋的”

所以

问题 1)
IShopInterface
的正确名称空间是什么

2) “替换”项目是否提供自己的接口或借用原始接口

3) 是否应该将原来的商店分成两个项目?(例如
Alice.Shop
Alice.ShopImplementation
因此
Alice.Shop
非常纤细,只包含接口?可能
Alice.Shop
Alice.Shop.Implementation
作为嵌套名称空间,但仍然有两个独立的代码库,因此您可以下载ans安装
Alice.Shop
)正在下载Alice.Shop.Implementation

4) 这是否像Bob在他的项目中包含
Alice.Shop.IShopInterface
文件的副本那样简单,因此不需要依赖项?非常难看-如果他这么做了,我们想拥有2家商店和
using Alice.Injector

namespace Bob.Shop
{
    public interface IShopService : IService
    {
        public void Show();
    }

    public class Shop : IShopService
    {
        public void Show()
        {
            // Here Bob does a brand new shop from scratch.
        }
    }
}
namespace Bob.Shop
{
    public class Shop : Alice.Shop.IShopService
    {
        public void Show()
        {
            // Here Bob does a brand new shop from scratch,
            // which borrows Alice's interface.
        }
    }
}
public class DefaultController
 {
   private readonly IShopService _shopService;

   DefaultController(IShopService shopService)
   {
     _shopService=shopService;
   }

   void OnShopClick()
   {
     _shopService.Show();
   }
  }