Dependency injection 注册期间Autofac解析服务的实现

Dependency injection 注册期间Autofac解析服务的实现,dependency-injection,autofac,service-locator,Dependency Injection,Autofac,Service Locator,我试图将代码放在一个地方,以便使用Autofac解析键控服务 我有一个界面: public interface IShipManagerService { } 两种实现方式: public class InventoryShipManagerService : IShipManagerService { } public class DemandShipManagerService : IShipManagerService { } 我还有一个UserProfileService,其中

我试图将代码放在一个地方,以便使用Autofac解析键控服务

我有一个界面:

public interface IShipManagerService { }
两种实现方式:

public class InventoryShipManagerService : IShipManagerService
{

}

public class DemandShipManagerService : IShipManagerService
{

}
我还有一个UserProfileService,其中包含一些会话信息:

public interface IUserProfileService 
{
    OrderType OrderingMode {get;set;}
}

public enum OrderType {Inventory, Demand}
基本上,一个用户会切换“模式”,我会在会话中保持这种状态

我想做的是使用键控注册解决IshipManager服务的正确实现,但我想把它放在一个位置

我有这个:

builder.RegisterType<InventoryShipManagerService>()
   .As<IShipManagerService>().Keyed<OrderType>(OrderType.Inventory);

builder.RegisterType<InventoryShipManagerService>()
   .As<IShipManagerService>().Keyed<OrderType>(OrderType.Inventory);
builder.RegisterType()
.As().Keyed(OrderType.Inventory);
builder.RegisterType()
.As().Keyed(OrderType.Inventory);
解析将使用Autofac推荐的IIndex

private readonly IShipManagerService _shipManagerService;
private readlony IUserProfileService _profileService;

public class ShipToController
{

     public ShipToController(IUserProfileService profileService, IIndex<OrderType, IShipManagerService> shipManagerList)
     {
         _profileService = profileService;
         _shipManagerService = shipManagerList[_profileService.OrderType];
     }
专用只读IShipManagerService\u shipManagerService;
私人readlony IUserProfileService(个人档案服务);
公共级船舶控制器
{
公共ShipToController(IUserProfileService profileService,IIndex ShipManager列表)
{
_profileService=profileService;
_shipManagerService=shipManagerList[_profileService.OrderType];
}
这是可行的——但我不想把它放在我使用IshipManager服务的任何地方(还有其他服务属于这一类)——我的控制器构造函数很快就会变得一团糟

我希望做的事情是这样的(我有这个工作)

builder.Register(ctx=>
{
//所以我可以得到当前的“订购模式”
var profileService=ctx.Resolve();
//默认为库存
IshipManager服务=(库存)激活器.CreateInstance(类型为(库存管理服务),
ctx.Resolve(),
ctx.Resolve())作为IShipManagerService;
交换机(profileService.OrderingMode)
{
案例排序模式。需求:
//如果需求“开启”
服务=(DemandShipManagerService)Activator.CreateInstance(类型为(DemandShipManagerService),
ctx.Resolve(),
ctx.Resolve())作为IShipmanagerService;
}
回程服务;
}
这里有两件事

  • 这是可行的,我知道这不是Autofac建议的(使用服务定位器模式)。但是,我觉得将服务解析代码放在我的应用程序的一个位置比使用服务解析组件中的正确类型更干净、更易于维护

  • 这看起来很难看。有没有办法使用密钥服务解析?换句话说,注册这两个服务,并让autofac根据解析的ProfileService.OrderingMode解析正确的已解析密钥(OrderType)服务实现

  • 我或多或少都在尝试验证我的方法。如果有人有更好的方法,我会很感激

    更新

    我正在尝试使用

    IIndex<T,V> 
    
    IIndex
    
    那个

    我觉得我离得很近,但我得到的服务没有注册例外

            _builder.RegisterType<TShelfShipToManagerService>().Keyed<IShipToManagerService>(OrderType.Shelf);
    
            _builder.RegisterType<TDemandShipToManagerService>().Keyed<IShipToManagerService>(OrderType.Demand);
    
            _builder.Register(ctx =>
            {
                var profileService = ctx.Resolve<IUserProfileService>();
    
                //The way Autofac recomends
                var services = ctx.Resolve<IIndex<OrderType, IShipToManagerService>>();
    
                //I get Component not Registered here??????
                return services[profileService.OrderingType];
    
    
                //this will go away if I can get the code above to work                
                IShipToManagerService service = Activator.CreateInstance(typeof(TShelfShipToManagerService),
                     ctx.Resolve<IRepository>(),
                     ctx.Resolve<IIntegrationService>(),
                     ctx.Resolve<IShoppingCartService>(),
                     ctx.Resolve<IUserProfileService>()
                     ) as IShipToManagerService;
    
                switch (profileService.OrderingType)
                {
                    case OrderType.Demand:
                        service = Activator.CreateInstance(typeof(TDemandShipToManagerService),
                            ctx.Resolve<IRepository>(),
                            ctx.Resolve<IIntegrationService>(),
                            ctx.Resolve<IShoppingCartService>(),
                            ctx.Resolve<IUserProfileService>()) as IShipToManagerService;
                        break;
                }
    
                return service;
            }).As<IShipToManagerService>();
    
    \u builder.RegisterType().Keyed(OrderType.Shelf);
    _builder.RegisterType().Keyed(OrderType.Demand);
    _builder.Register(ctx=>
    {
    var profileService=ctx.Resolve();
    //Autofac重新编译的方式
    var services=ctx.Resolve();
    //我得到的组件没有在这里注册??????
    返回服务[profileService.OrderingType];
    //如果我能让上面的代码工作,这将消失
    IShipToManagerService服务=Activator.CreateInstance(类型为(TShelfShipToManagerService),
    ctx.Resolve(),
    ctx.Resolve(),
    ctx.Resolve(),
    ctx.Resolve()
    )作为IShipToManagerService;
    交换机(profileService.OrderingType)
    {
    案例订单类型。需求:
    service=Activator.CreateInstance(类型为(TDemandShipToManagerService),
    ctx.Resolve(),
    ctx.Resolve(),
    ctx.Resolve(),
    ctx.Resolve())作为IShipToManagerService;
    打破
    }
    回程服务;
    }).As();
    
    我不知道为什么这不起作用。

    已经解决了

    结果我有两件事做错了

  • 我从未使用要解决的接口注册服务

        _builder.RegisterType<TShelfShipToManagerService>()
            .Keyed<IShipToManagerService>(OrderType.Shelf)
            .As<IShipToManagerService>();  //was missing that part
    
        _builder.RegisterType<TDemandShipToManagerService>()
            .Keyed<IShipToManagerService>(OrderType.Demand)
            .As<IShipToManagerService>();  //was missing that part
    
    \u builder.RegisterType()
    .Keyed(OrderType.Shelf)
    .As();//缺少该部分
    _builder.RegisterType()
    .Keyed(OrderType.Demand)
    .As();//缺少该部分
    
  • 该方法假设订购模式可以从UserProfile服务获得。我在中进行了足够的异常处理,以确保它们是默认的UserProfile服务(对于启动和用户登录之前,没有任何异常)。问题是我试图针对排序模式为0的键控服务进行解决(因为排序模式是一个枚举,并且不是由用户会话设置的,所以它被设置为零)

  • 在上面,我只注册了两个键控服务OrderType.Shelf和OrderType.Demand-所以什么时候

           _builder.Register(ctx =>
            {
                var profileService = ctx.Resolve<IUserProfileService>();
    
    
                //The way Autofac recomends
                var services = ctx.Resolve<IIndex<OrderType, IShipToManagerService>>();
    
                //The first request ends up with an OrderingType == 0
                //Since I haven established the session 
                //I don't have service registered with a key 0
                return services[profileService.OrderingType];
            }).As<IShipToManagerService>();
    
    \u builder.Register(ctx=>
    {
    var profileService=ctx.Resolve();
    //Autofac重新编译的方式
    var services=ctx.Resolve();
    //第一个请求以OrderingType==0结束
    //因为我还没有建立会议
    //我没有使用密钥0注册服务
    返回服务[profileService.OrderingType];
    }).As();
    
    因此,修复方法只是检查OrderingType==0——如果是,则使用默认设置

    这里我有一个AppSettingService,它提供了一个全局设置DefaultOrderingMode

            _builder.Register(ctx =>
            { var profileService = ctx.Resolve<IUserProfileService>();
    
                //Check to see if their is a user profile (OrderType = 0) 
                //if not - then get the default setting
                if (profileService.OrderingType == 0)
                {
                    var appSettingService = ctx.Resolve<IApplicationSettingService>();
    
                    profileService.OrderingType = appSettingService.GetApplicationSetting(ApplicationSettings.DefaultOrderingMode).ToEnumTypeOf<OrderType>();
                }
                //The way Autofac recomends
                var services = ctx.Resolve<IIndex<OrderType, IShipToManagerService>>();
                return services[profileService.OrderingType];
    
            }).As<IShipToManagerService>();
    
    \u builder.Register(ctx=>
    {var profileService=ctx.Resolve();
    //检查他们的电脑是否为
    
            _builder.Register(ctx =>
            { var profileService = ctx.Resolve<IUserProfileService>();
    
                //Check to see if their is a user profile (OrderType = 0) 
                //if not - then get the default setting
                if (profileService.OrderingType == 0)
                {
                    var appSettingService = ctx.Resolve<IApplicationSettingService>();
    
                    profileService.OrderingType = appSettingService.GetApplicationSetting(ApplicationSettings.DefaultOrderingMode).ToEnumTypeOf<OrderType>();
                }
                //The way Autofac recomends
                var services = ctx.Resolve<IIndex<OrderType, IShipToManagerService>>();
                return services[profileService.OrderingType];
    
            }).As<IShipToManagerService>();