Simple Injector:依赖于http请求的实现
Simple Injector: Implementation that depends on http request
我是 Simple Injector 的初学者,有一个场景需要帮助来实现。我会尽量简化我需要做的事情。
我有一个 WebAPI,我需要在其中对用户进行身份验证,并根据用户类型选择一个实现。
考虑这个结构
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 上配置不需要此逻辑的存储库和其他接口,但是,由于这种情况我需要请求来决定应该使用哪个实现,我想我需要解决这以其他方式。
有"Simple Injector"的方法来处理这个问题吗?还是我应该尝试另一种方法?
最简单的解决方案是在 composition root 中配置决策以及容器的其余配置:
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
var container = new Container();
container.Register<CarLogicStandard>();
container.Register<CarLogicPremium>();
container.RegisterPerWebRequest<ICarRepository, CarRepository>();
container.Register<ICarLogic>(
() =>
HttpContext.Current != null &&
HttpContext.Current.User != null &&
HttpContext.Current.User.IsInRole("Premium")
? (ICarLogic)container.GetInstance<CarLogicPremium>()
: (ICarLogic)container.GetInstance<CarLogicStandard>()
);
// This is an extension method from the integration package.
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
}
您还可以创建对当前用户的抽象,并使用 高级 功能
装饰标准 功能
public class CarLogicPremium : ICarLogic
{
private readonly ICarLogic decorated;
private readonly ICurrentUser currentUser;
private readonly ICarRepository carRepository;
public CarLogicPremium(
ICarLogic decorated,
ICurrentUser currentUser,
ICarRepository carRepository)
{
this.decorated = decorated;
this.currentUser = currentUser;
this.carRepository = carRepository;
}
public void CreateCar(Car car)
{
if (currentUser.IsPremiumMember)
{
car.Color = "Red";
this.carRepository.SaveCar(car);
//Other stuff 2...
}
else
{
this.decorated.CreateCar(car);
}
}
}
配置有点像这样
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
var container = new Container();
container.Register<ICurrentUser, HttpCurrentUserProxy>();
container.RegisterPerWebRequest<ICarRepository, CarRepository>();
container.Register<ICarLogic, CarLogicStandard>();
container.RegisterDecorator(typeof(ICarLogic), typeof(CarLogicPremium));
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
}
但这实际上取决于您将随着时间的推移创建多少种服务变体。如果您将不断添加新的高级功能,您应该考虑实现 Try-X 模式的变体。让我知道以上其中一项是否适合您,或者您是否需要更多信息...
我是 Simple Injector 的初学者,有一个场景需要帮助来实现。我会尽量简化我需要做的事情。
我有一个 WebAPI,我需要在其中对用户进行身份验证,并根据用户类型选择一个实现。
考虑这个结构
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 上配置不需要此逻辑的存储库和其他接口,但是,由于这种情况我需要请求来决定应该使用哪个实现,我想我需要解决这以其他方式。
有"Simple Injector"的方法来处理这个问题吗?还是我应该尝试另一种方法?
最简单的解决方案是在 composition root 中配置决策以及容器的其余配置:
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
var container = new Container();
container.Register<CarLogicStandard>();
container.Register<CarLogicPremium>();
container.RegisterPerWebRequest<ICarRepository, CarRepository>();
container.Register<ICarLogic>(
() =>
HttpContext.Current != null &&
HttpContext.Current.User != null &&
HttpContext.Current.User.IsInRole("Premium")
? (ICarLogic)container.GetInstance<CarLogicPremium>()
: (ICarLogic)container.GetInstance<CarLogicStandard>()
);
// This is an extension method from the integration package.
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
}
您还可以创建对当前用户的抽象,并使用 高级 功能
装饰标准 功能public class CarLogicPremium : ICarLogic
{
private readonly ICarLogic decorated;
private readonly ICurrentUser currentUser;
private readonly ICarRepository carRepository;
public CarLogicPremium(
ICarLogic decorated,
ICurrentUser currentUser,
ICarRepository carRepository)
{
this.decorated = decorated;
this.currentUser = currentUser;
this.carRepository = carRepository;
}
public void CreateCar(Car car)
{
if (currentUser.IsPremiumMember)
{
car.Color = "Red";
this.carRepository.SaveCar(car);
//Other stuff 2...
}
else
{
this.decorated.CreateCar(car);
}
}
}
配置有点像这样
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
var container = new Container();
container.Register<ICurrentUser, HttpCurrentUserProxy>();
container.RegisterPerWebRequest<ICarRepository, CarRepository>();
container.Register<ICarLogic, CarLogicStandard>();
container.RegisterDecorator(typeof(ICarLogic), typeof(CarLogicPremium));
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
}
但这实际上取决于您将随着时间的推移创建多少种服务变体。如果您将不断添加新的高级功能,您应该考虑实现 Try-X 模式的变体。让我知道以上其中一项是否适合您,或者您是否需要更多信息...