Asp.net web api 简单注入器:依赖于http请求的实现
我是一个简单注射器的初学者,有一个需要帮助实现的场景。我会尽量简化我需要做的事情 我有一个WebAPI,需要对用户进行身份验证,并根据用户类型选择实现 以这种结构为例Asp.net web api 简单注入器:依赖于http请求的实现,asp.net-web-api,dependency-injection,inversion-of-control,simple-injector,Asp.net Web Api,Dependency Injection,Inversion Of Control,Simple Injector,我是一个简单注射器的初学者,有一个需要帮助实现的场景。我会尽量简化我需要做的事情 我有一个WebAPI,需要对用户进行身份验证,并根据用户类型选择实现 以这种结构为例 public interface ICarRepository { void SaveCar(Car car); } //Some implementation for ICarRepository public interface ICarLogic { void CreateCar(Car car); }
public interface ICarRepository {
void SaveCar(Car car);
}
//Some implementation for ICarRepository
public interface ICarLogic {
void CreateCar(Car car);
}
public class CarLogicStandard: ICarLogic {
private ICarRepository _carRepository;
public CarLogicStandard(ICarRepository carRepository) {
_carRepository = carRepository;
}
public void CreateCar(Car car) {
car.Color = "Blue";
_carRepository.SaveCar();
//Other stuff...
}
}
public class CarLogicPremium: ICarLogic {
private ICarRepository _carRepository;
public CarLogicPremium(ICarRepository carRepository) {
_carRepository = carRepository;
}
public void CreateCar(Car car) {
car.Color = "Red";
_carRepository.SaveCar();
//Other stuff 2...
}
}
现在我有了一个控制器
public class CarController: ApiController {
private ICarLogic _carLogic;
public CarController(ICarLogic carLogic) {
_carLogic = carLogic;
}
public void Post(somePostData) {
//Identify the user based on post data
//....
Car car = somePostData.SomeCar();
_carLogic.CreateCar(car);
}
}
上面的代码将不起作用,因为在我的请求中,我需要标识用户。如果是高级用户,控制器应使用CarLogicPremium;如果是标准用户,控制器应使用CarLogicStandard
我可以在Global.asax上配置不需要此逻辑的存储库和其他接口。但是,由于这种情况下我需要请求来决定应该使用哪种实现,因此我建议我需要以其他方式解决此问题
有一种“简单的喷油器”方法来处理这个问题吗?还是我应该尝试另一种方法 最简单的解决方案是在中配置决策,以及容器的其余配置:
受保护的无效应用程序\u Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
var container=新容器();
container.Register();
container.Register();
container.registerWebRequest();
集装箱。登记(
() =>
HttpContext.Current!=null&&
HttpContext.Current.User!=null&&
HttpContext.Current.User.IsInRole(“高级”)
?(ICarLogic)容器。GetInstance()
:(ICarLogic)container.GetInstance()
);
//这是集成包中的扩展方法。
容器.RegisterWebApp控制器(全局配置.Configuration);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver=
新的SimpleInjectorWebApidencyResolver(容器);
}
您还可以为当前用户创建一个抽象,并用高级功能装饰标准功能
公共类CarLogicPremium:ICarLogic
{
私人只读ICarLogic;
专用只读ICurrentUser currentUser;
私人只读易读存储;
公共图书馆(
伊卡洛斯,
ICurrentUser当前用户,
i沉淀(沉淀)
{
这是装饰过的;
this.currentUser=currentUser;
this.carRepository=carRepository;
}
公共汽车
{
if(currentUser.ispremiummber)
{
car.Color=“Red”;
这个。carRepository。SaveCar(car);
//其他资料2。。。
}
其他的
{
这个。装饰。创造汽车(汽车);
}
}
}
它的配置有点像这样
受保护的无效应用程序\u Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
var container=新容器();
container.Register();
container.registerWebRequest();
container.Register();
容器注册检测器(类型为(ICarLogic),类型为(CarLogicPremium));
容器.RegisterWebApp控制器(全局配置.Configuration);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver=
新的SimpleInjectorWebApidencyResolver(容器);
}
但这实际上取决于随着时间的推移,您将创建多少不同的服务。如果您将不断添加新的高级功能,您应该考虑实现Try-X模式的变体。让我知道上述其中一项是否适用于您,或者您是否需要更多信息…为什么不使用工厂来解决
ICarLogic
接口的所需实现?老实说,你不应该仅仅因为用户类型而有两种不同的实现,如果你最终添加了更多的用户类型呢?嘿,谢谢你的帮助。您会推荐什么来代替接口实现?您是对的,将存在更多的用户类型,其中一些将需要更改某些类的行为。。。我应该为每个不同的行为创建不同的界面吗?嗨,谢谢你的帮助。回答很好,但是我在这一行遇到了一个问题:(ICarLogic)container.GetInstance()“CarLogicPremium类型的注册委托引发了一个异常。无法拦截CarLogicPremium类型,因为它不是一个接口。”即使注册CarLogicPremium,您知道为什么吗?@Rafael您通常使用的是,我的建议是,在构建对象图期间,不要对运行时数据做出决策。因此,我不建议@qujck给出第一个答案,但我同意他的第二个建议:使用一个facade/proxy/decorator,通过正确的实现进行委托。@qujck是的,我在我的项目上有拦截扩展。是它导致了问题吗?@qujck是的,我对拦截进行了评论,效果很好。因为这只是一个练习的例子,如果这个问题发生在一个有意义的场景中,我将在稍后研究它。非常感谢两种解决方案!