如何将 DbContext 实现注入 Prism ViewModel 构造函数?
How to inject DbContext implementation into Prism ViewModel constructor?
我正在使用 Unity 和 Entity Framework 开发 WPF Prism 应用程序。我希望在构建 ViewModel 时注入我的自定义 DbContext,这样我就可以在 ViewModel 的整个生命周期中使用它。 DbContext class 所在的模块在 Bootstrapper 中注册,DbContext 类型在 Module.Initialize().
期间注册
综上所述,在尝试构造注入 DbContext 的 ViewModel 时抛出运行时错误。它说 IDbConnection 需要注册。当我向模块注册它时,它会说 DbConnection 是一个抽象 class 并且无法构造。关于应该如何注册 DbContext,肯定有一些我不知道的事情。
这是在模块中注册类型的位置:
public class SharedResourcesModule : IModule
{
IUnityContainer container;
public SharedResourcesModule(IUnityContainer container)
{
this.container = container;
}
public void Initialize()
{
container.RegisterType<IAuthenticationService, AuthenticationService>();
container.RegisterType<IDataBaseContext, EFDbContext>();
}
}
以及 ViewModel 构造函数的示例:
public class ProductContextResultViewModel : ViewModelBase
{
public ProductContextResultViewModel(IDataBaseContext dataBaseContext)
{
this.DataBaseContext = dataBaseContext as EFDbContext;
}
private EFDbContext DataBaseContext { get; set; }
}
如果我可以提供任何其他详细信息,请告诉我!
异常详情如下:
Microsoft.Practices.ServiceLocation.ActivationException 未被用户代码处理
HResult=-2146233088
消息=尝试获取对象类型的实例时发生激活错误,密钥 "ProductContextResultView"
来源=Microsoft.Practices.ServiceLocation
堆栈跟踪:
在 Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key) 在 c:\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:line 53
在 Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance[TService](String key) 在 c:\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:line 103
在 Microsoft.Practices.Prism.Regions.RegionNavigationContentLoader.CreateNewRegionItem(String candidateTargetContract)
内部异常:Microsoft.Practices.Unity.ResolutionFailedException
HResult=-2146233088
Message=解析依赖失败,类型="System.Object",名称="ProductContextResultView"。
异常发生在:解析时。
异常是:InvalidOperationException - 当前类型 System.Data.Common.DbConnection 是一个抽象 class,无法构造。您是否缺少类型映射?
发生异常时,容器是:
正在解析 ContextResultsPane.ProductContextResult.ProductContextResultView,ProductContextResultView(映射自 System.Object,ProductContextResultView)
正在解析构造函数 ContextResultsPane.ProductContextResult.ProductContextResultView(ContextResultsPane.ProductContextResult.ProductContextResultViewModel viewModel) 的参数 "viewModel"
正在解析 ContextResultsPane.ProductContextResult.ProductContextResultView模型,(none)
构造函数 ContextResultsPane.ProductContextResult.ProductContextResultViewModel(SharedResources.DataAccess.IDataBaseContext dataBaseContext) 的解析参数 "dataBaseContext"
解析 SharedResources.DataAccess.EFDbContext,(none)(映射自 SharedResources.DataAccess.IDataBaseContext, (none))
解析构造函数SharedResources.DataAccess.EFDbContext的参数"connection"(System.Data.Common.DbConnection连接)
解析 System.Data.Common.DbConnection,(none)
Source=Microsoft.Practices.Unity
NameRequested=ProductContextResultView
TypeRequested=Object
StackTrace:
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, String name, IEnumerable`1 resolverOverrides)
at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides)
at Microsoft.Practices.Prism.UnityExtensions.UnityServiceLocatorAdapter.DoGetInstance(Type serviceType, String key)
at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key) in c:\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:line 49
InnerException: System.InvalidOperationException
HResult=-2146233079
Message=The current type, System.Data.Common.DbConnection, is an abstract class and cannot be constructed. Are you missing a type mapping?
Source=Microsoft.Practices.Unity
StackTrace:
at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.ThrowForAttemptingToConstructAbstractClass(IBuilderContext context)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey)
at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey)
at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey)
at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
InnerException:
Glen Thomas 的指导帮助我进行了更多阅读,事实证明 Unity 默认使用最冗长的构造函数。这是问题的核心,因为我有一个构造函数需要为单元测试传递 DbConnection。
为了强制 Unity 使用默认构造函数,我更改了这个...
container.RegisterType<IDataBaseContext, EFDbContext>();
...到此...
container.RegisterType<IDataBaseContext, EFDbContext>(new InjectionConstructor());
更改后它按预期工作!
我正在使用 Unity 和 Entity Framework 开发 WPF Prism 应用程序。我希望在构建 ViewModel 时注入我的自定义 DbContext,这样我就可以在 ViewModel 的整个生命周期中使用它。 DbContext class 所在的模块在 Bootstrapper 中注册,DbContext 类型在 Module.Initialize().
期间注册综上所述,在尝试构造注入 DbContext 的 ViewModel 时抛出运行时错误。它说 IDbConnection 需要注册。当我向模块注册它时,它会说 DbConnection 是一个抽象 class 并且无法构造。关于应该如何注册 DbContext,肯定有一些我不知道的事情。
这是在模块中注册类型的位置:
public class SharedResourcesModule : IModule
{
IUnityContainer container;
public SharedResourcesModule(IUnityContainer container)
{
this.container = container;
}
public void Initialize()
{
container.RegisterType<IAuthenticationService, AuthenticationService>();
container.RegisterType<IDataBaseContext, EFDbContext>();
}
}
以及 ViewModel 构造函数的示例:
public class ProductContextResultViewModel : ViewModelBase
{
public ProductContextResultViewModel(IDataBaseContext dataBaseContext)
{
this.DataBaseContext = dataBaseContext as EFDbContext;
}
private EFDbContext DataBaseContext { get; set; }
}
如果我可以提供任何其他详细信息,请告诉我!
异常详情如下:
Microsoft.Practices.ServiceLocation.ActivationException 未被用户代码处理 HResult=-2146233088 消息=尝试获取对象类型的实例时发生激活错误,密钥 "ProductContextResultView" 来源=Microsoft.Practices.ServiceLocation 堆栈跟踪: 在 Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key) 在 c:\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:line 53 在 Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance[TService](String key) 在 c:\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:line 103 在 Microsoft.Practices.Prism.Regions.RegionNavigationContentLoader.CreateNewRegionItem(String candidateTargetContract) 内部异常:Microsoft.Practices.Unity.ResolutionFailedException HResult=-2146233088 Message=解析依赖失败,类型="System.Object",名称="ProductContextResultView"。 异常发生在:解析时。
异常是:InvalidOperationException - 当前类型 System.Data.Common.DbConnection 是一个抽象 class,无法构造。您是否缺少类型映射?
发生异常时,容器是:
正在解析 ContextResultsPane.ProductContextResult.ProductContextResultView,ProductContextResultView(映射自 System.Object,ProductContextResultView) 正在解析构造函数 ContextResultsPane.ProductContextResult.ProductContextResultView(ContextResultsPane.ProductContextResult.ProductContextResultViewModel viewModel) 的参数 "viewModel" 正在解析 ContextResultsPane.ProductContextResult.ProductContextResultView模型,(none) 构造函数 ContextResultsPane.ProductContextResult.ProductContextResultViewModel(SharedResources.DataAccess.IDataBaseContext dataBaseContext) 的解析参数 "dataBaseContext" 解析 SharedResources.DataAccess.EFDbContext,(none)(映射自 SharedResources.DataAccess.IDataBaseContext, (none)) 解析构造函数SharedResources.DataAccess.EFDbContext的参数"connection"(System.Data.Common.DbConnection连接) 解析 System.Data.Common.DbConnection,(none)
Source=Microsoft.Practices.Unity
NameRequested=ProductContextResultView
TypeRequested=Object
StackTrace:
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, String name, IEnumerable`1 resolverOverrides)
at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides)
at Microsoft.Practices.Prism.UnityExtensions.UnityServiceLocatorAdapter.DoGetInstance(Type serviceType, String key)
at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key) in c:\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:line 49
InnerException: System.InvalidOperationException
HResult=-2146233079
Message=The current type, System.Data.Common.DbConnection, is an abstract class and cannot be constructed. Are you missing a type mapping?
Source=Microsoft.Practices.Unity
StackTrace:
at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.ThrowForAttemptingToConstructAbstractClass(IBuilderContext context)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey)
at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey)
at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey)
at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
InnerException:
Glen Thomas 的指导帮助我进行了更多阅读,事实证明 Unity 默认使用最冗长的构造函数。这是问题的核心,因为我有一个构造函数需要为单元测试传递 DbConnection。
为了强制 Unity 使用默认构造函数,我更改了这个...
container.RegisterType<IDataBaseContext, EFDbContext>();
...到此...
container.RegisterType<IDataBaseContext, EFDbContext>(new InjectionConstructor());
更改后它按预期工作!