Simple Injector:依赖于http请求的实现

时间:2015-03-29 18:50:38

标签: asp.net-web-api dependency-injection inversion-of-control simple-injector

我是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上配置不需要这个逻辑的存储库和其他接口,但是,由于这种情况我需要决定应该使用哪个实现,我想我需要在其他一些中解决这个问题。方式。

有一种“简单的注射器”方式来处理这个问题?或者我应该尝试另一种方法?

1 个答案:

答案 0 :(得分:2)

最简单的解决方案是在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);
}

您还可以为当前用户创建抽象,并使用 premium 功能装饰标准功能

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 模式的变体。如果以上其中一项适合您或您需要更多信息,请告诉我......

相关问题