我有这样的命令接口:
public interface ICommand { }
public interface ICommand<in TEntity> : ICommand { }
public interface ICommandHandler<in TCommand> where TCommand : class, ICommand
{
void Handle(TCommand command);
}
我的一个通用命令如下:
public class ChangeCommand<TEntity> : ICommand<TEntity> where TEntity : class, IEntity
{
public TEntity entityToChange { get; set; }
}
我使用的是最新版本的SimpleInjector。我的商家配置如下:
public class BusinessLayerBootstrapper
{
public static void Bootstrap(Container container)
{
if(container == null)
{
throw new ArgumentNullException("BusinessLayerBootstrapper container");
}
container.RegisterSingleton<IValidator>(new DataAnnotationsValidator(container));
var typesToRegister = container.GetTypesToRegister(typeof(ICommandHandler<>),
AppDomain.CurrentDomain.GetAssemblies(),
new TypesToRegisterOptions
{
IncludeGenericTypeDefinitions = true,
IncludeDecorators = false,
IncludeComposites = false
});
container.RegisterCollection(typeof(ICommandHandler<>), typesToRegister);
container.RegisterDecorator(typeof(ICommandHandler<>), typeof(PostCommitCommandHandlerDecorator<>));
container.Register<IPostCommitRegistrator>(() => container.GetInstance<PostCommitRegistrator>(), Lifestyle.Scoped);
container.RegisterDecorator(typeof(ICommandHandler<>), typeof(TransactionCommandHandlerDecorator<>));
container.RegisterDecorator(typeof(ICommandHandler<>), typeof(ValidationCommandHandlerDecorator<>));
container.RegisterDecorator(typeof(ICommandHandler<>), typeof(AuthorizationCommandHandlerDecorator<>));
container.Register(typeof(IQueryHandler<,>), AppDomain.CurrentDomain.GetAssemblies());
container.RegisterDecorator(typeof(IQueryHandler<,>), typeof(AuthorizationQueryHandlerDecorator<,>));
}
}
ASP.NET MVC配置:
public class Bootstrapper
{
public static void Bootstrap()
{
Container container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
Business.BusinessLayerBootstrapper.Bootstrap(container);
container.Register<IPrincipal>(() => HttpContext.Current.User ?? Thread.CurrentPrincipal);
container.RegisterSingleton<ILogger>(new FileLogger());
container.Register<IUnitOfWork>(() => new UnitOfWork(ConfigurationManager.ConnectionStrings["PriceMonitorMSSQLConnection"].ConnectionString), Lifestyle.Scoped);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Verify(VerificationOption.VerifyAndDiagnose);
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
}
在控制器中我有这样的代码:
public class HomeController : Controller
{
ICommandHandler<ICommand<Product>> CreateProduct;
ICommandHandler<ICommand<Product>> ChangeProduct;
ICommandHandler<ICommand<Product>> DeleteProduct;
ICommandHandler<ChangeProductWpriceCommand> ChangeProductWprice;
IQueryHandler<ProdStoreHierByUserQuery, IEnumerable<ProductStoreHierarchy>> PSTree;
IQueryHandler<ProdStoreStatByProdIdUserPeriodQuery, IEnumerable<ProductStoreStatistic>> Statistic;
public HomeController(ICommandHandler<ICommand<Product>> CreateProduct,
ICommandHandler<ICommand<Product>> ChangeProduct,
ICommandHandler<ICommand<Product>> DeleteProduct,
ICommandHandler<ChangeProductWpriceCommand> ChangeProductWprice,
IQueryHandler<ProdStoreHierByUserQuery, IEnumerable<ProductStoreHierarchy>> PSTree,
IQueryHandler<ProdStoreStatByProdIdUserPeriodQuery, IEnumerable<ProductStoreStatistic>> Statistic)
{
this.CreateProduct = CreateProduct;
this.ChangeProduct = ChangeProduct;
this.DeleteProduct = DeleteProduct;
this.ChangeProductWprice = ChangeProductWprice;
this.PSTree = PSTree;
this.Statistic = Statistic;
}
// some actions...
}
结果container.Verify
方法抛出异常:
类型&#39; System.InvalidOperationException&#39;的例外情况发生在SimpleInjector.dll中但未在用户代码中处理
其他信息:配置无效。为类型HomeController创建实例失败。 HomeController类型的构造函数包含名称为&#39; CreateProduct&#39;的参数。并输入ICommandHandler&lt; ICommand&lt; Product&gt;&gt;那是没有注册的。请确保已注册
ICommandHandler<ICommand<Product>>
,或更改HomeController的构造函数。但是,有IEnumerable<ICommandHandler<ICommand<Product>>>
的注册;您的意思是依赖IEnumerable<ICommandHandler<ICommand<Product>>>
吗?
如果我不使用RegisterCollection
方法,则会抛出相同的异常。能否请你给我一个如何解决这个问题的建议?
已更新
根据史蒂文的评论,我根据给定的建议编辑了我的问题。我现在注册的是:
//container.RegisterCollection(typeof(ICommandHandler<>), typesToRegister);
// is replaced with
container.Register(typeof(ICommandHandler<>), typesToRegister);
// ...
Register
抛出异常:
提供的类型列表包含一个或多个开放泛型类型,但此方法无法处理开放泛型类型,因为它只能将封闭的通用服务类型映射到单个实现。请尝试使用RegisterCollection。无效类型:ChangeCommandHandler&lt; TEntity&gt;,CreateCommandHandler&lt; TEntity&gt;和DeleteCommandHandler&lt; TEntity&gt;。 参数名称:implementationTypes
如果我将以前的代码留给第一个变体,但会将我的控制器更改为:
ICommandHandler<CreateCommand<Product>> CreateProduct;
ICommandHandler<ChangeCommand<Product>> ChangeProduct;
ICommandHandler<DeleteCommand<Product>> DeleteProduct;
ICommandHandler<ChangeProductWpriceCommand> ChangeProductWprice;
IQueryHandler<ProdStoreHierByUserQuery, IEnumerable<ProductStoreHierarchy>> PSTree;
IQueryHandler<ProdStoreStatByProdIdUserPeriodQuery, IEnumerable<ProductStoreStatistic>> Statistic;
public HomeController(ICommandHandler<CreateCommand<Product>> CreateProduct,
ICommandHandler<ChangeCommand<Product>> ChangeProduct,
ICommandHandler<DeleteCommand<Product>> DeleteProduct,
ICommandHandler<ChangeProductWpriceCommand> ChangeProductWprice,
IQueryHandler<ProdStoreHierByUserQuery, IEnumerable<ProductStoreHierarchy>> PSTree,
IQueryHandler<ProdStoreStatByProdIdUserPeriodQuery, IEnumerable<ProductStoreStatistic>> Statistic)
{
this.CreateProduct = CreateProduct;
this.ChangeProduct = ChangeProduct;
this.DeleteProduct = DeleteProduct;
this.ChangeProductWprice = ChangeProductWprice;
this.PSTree = PSTree;
this.Statistic = Statistic;
}
然后Verify
方法抛出类似于第一个的异常:
配置无效。为类型HomeController创建实例失败。 HomeController类型的构造函数包含名称为&#39; CreateProduct&#39;的参数。并键入ICommandHandler&lt; CreateCommand&lt; Product&gt;&gt;那是没有注册的。请确保ICommandHandler&lt; CreateCommand&lt; Product&gt;&gt;已注册,或更改HomeController的构造函数。但是,IEnumerable&lt; ICommandHandler&lt; CreateCommand&lt; Product&gt;&gt;&gt;的注册;你的意思是依赖于IEnumerable&lt; ICommandHandler&lt; CreateCommand&lt; Product&gt;&gt;&gt;?
也许您可以通过Repository
模式向我提供如何解决此问题的建议?