内核出现InvalidCastException.获取<;键入>;
本文关键字:lt 键入 gt 获取 InvalidCastException 内核 | 更新日期: 2023-09-27 18:20:19
我有一个WPF应用程序,它可能使用命令行参数启动,也可能不使用命令行args启动。我过去在App.xaml代码后面的OnStartup(StartupEventArgs e)
方法中有我的合成根,但这会导致应用程序关闭问题,所以我把App.xaml变成了一个"页面"(而不是"应用程序定义"),并编写了我自己的Program
类,其中包含我自己的应用程序入口点,这将成为我的新合成根位置。
自从那次更改以来,我一直无法启动应用程序,Ninject似乎无法解析应用程序的主要对象(或者它可能是它的依赖项之一?)。
这个异常让我浪费了很多时间,堆栈跟踪都是Ninject内部的,我不知道在我的代码中该修复什么,我绑定导致这个异常的类型的方式最近没有改变:
at DynamicInjector54d92ac63a2e47fda5ffbcc19b9942a9(Object[] )
at Ninject.Activation.Providers.StandardProvider.Create(IContext context)
at Ninject.Activation.Context.Resolve()
at Ninject.KernelBase.<>c__DisplayClass10.<Resolve>b__c(IBinding binding)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
at Ninject.Planning.Targets.Target`1.GetValue(Type service, IContext parent)
at Ninject.Planning.Targets.Target`1.ResolveWithin(IContext parent)
at Ninject.Activation.Providers.StandardProvider.GetValue(IContext context, ITarget target)
at Ninject.Activation.Providers.StandardProvider.<>c__DisplayClass4.<Create>b__2(ITarget target)
at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Ninject.Activation.Providers.StandardProvider.Create(IContext context)
at Ninject.Activation.Context.Resolve()
at Ninject.KernelBase.<>c__DisplayClass10.<Resolve>b__c(IBinding binding)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
at Ninject.Planning.Targets.Target`1.GetValue(Type service, IContext parent)
at Ninject.Planning.Targets.Target`1.ResolveWithin(IContext parent)
at Ninject.Activation.Providers.StandardProvider.GetValue(IContext context, ITarget target)
at Ninject.Activation.Providers.StandardProvider.<>c__DisplayClass4.<Create>b__2(ITarget target)
at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Ninject.Activation.Providers.StandardProvider.Create(IContext context)
at Ninject.Activation.Context.Resolve()
at Ninject.KernelBase.<>c__DisplayClass10.<Resolve>b__c(IBinding binding)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
at Ninject.Planning.Targets.Target`1.GetValue(Type service, IContext parent)
at Ninject.Planning.Targets.Target`1.ResolveWithin(IContext parent)
at Ninject.Activation.Providers.StandardProvider.GetValue(IContext context, ITarget target)
at Ninject.Activation.Providers.StandardProvider.<>c__DisplayClass4.<Create>b__2(ITarget target)
at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Ninject.Activation.Providers.StandardProvider.Create(IContext context)
at Ninject.Activation.Context.Resolve()
at Ninject.KernelBase.<>c__DisplayClass10.<Resolve>b__c(IBinding binding)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.<CastIterator>d__b1`1.MoveNext()
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at Ninject.ResolutionExtensions.Get[T](IResolutionRoot root, IParameter[] parameters)
at MyProgram.Program.Main(String[] args) in C:'Dev'MyProject'MyProject.WinPresentation'Program.cs:ligne 40
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
以下是Main
方法/应用程序入口点:
[STAThread]
public static void Main(string[] args)
{
var module = new MyAppNinjectModule(args);
var kernel = new StandardKernel(module);
var argsHelper = module.CommandLineArgs;
var logProvider = kernel.Get<ILogProvider>();
var logger = logProvider.GetLogger(typeof(Program).Name);
if (argsHelper.LoggingDisabledArgument.IsSpecified()) logProvider.DisableLogging();
logger.Info(log.LogAppStart);
var installer = kernel.Get<IInstaller>(); // >>> InvalidCastException here
if (argsHelper.QuietInterfaceArgument.IsSpecified())
{
// running with -quiet command-line switch: just execute and exit.
installer.Execute();
}
else
{
// instantiate a new App object (WPF), and run it.
// installer.Execute() may or may not be executed, depending on user actions.
var app = new App(installer);
app.Run();
}
}
根据提供的命令行参数,NinjectModule将IInstaller
绑定到这样或那样的实现(例如,指定了QuietInterfaceArgument
时为SilentInstaller
,未指定时为ManualInstaller
,等等)
通常,Ninject会给非常有用和详细的异常消息——当它是ActivationException
时,生命是美好的。但这个InvalidCastException
让我一无所知,我不是执行无效强制转换的人,我甚至不知道涉及到什么类型。我只知道我可能写了一些Ninject不喜欢的代码,也许这与我将IInstaller
绑定到其实现的方式有关,但如果我注释掉NinjectModule的"分支"部分以强制绑定我想要的特定实现(ManualInstaller
),它仍然无法使用此InvalidCastException
。
实现的构造函数:
public ManualInstaller(IView<MainWindowViewModel> view,
IProcessHelper processHelper,
ISettingsHelper settingsHelper,
ILogProvider logProvider,
ISetupBootstrapper installer,
bool notifySuccess)
: base(notifySuccess, processHelper, settingsHelper, logProvider, installer)
相应的绑定代码(其他依赖项已经绑定,没有ActivationException
,所以不确定这与我的问题有多相关):
var msg = string.Empty;
if (CommandLineArgs.CompletionMessageArgument.IsSpecified())
msg = CommandLineArgs.CompletionMessageArgument.ParameterValue();
Bind<MainWindowViewModel>().ToSelf().WithConstructorArgument("completionMessage", msg);
Bind<IView<MainWindowViewModel>>().To<MainWindow>();
Bind<IInstaller>().To<ManualInstaller>()
.WithConstructorArgument("notifySuccess", notifySuccess);
如果还需要其他东西来了解发生了什么,请毫不犹豫地告诉我…
编辑
单独解决安装程序的依赖关系会产生更多信息:
// resolve installer dependencies:
var view = kernel.Get<IView<MainWindowViewModel>>(); // >>> InvalidCastException here
var processHelper = kernel.Get<IProcessHelper>();
var settingsHelper = kernel.Get<ISettingsHelper>();
var bootstrapper = kernel.Get<ISetupBootstrapper>();
var installer = new ManualInstaller(view, processHelper, settingsHelper, logProvider, bootstrapper, true);
因此,我至少可以将其缩小到我试图解决的类型的一个特定依赖项:问题要么是View,要么是它唯一的依赖项ViewModel。所以我做了这个:
// resolve ViewModel dependencies:
var processHelper = kernel.Get<IProcessHelper>(); // >>> InvalidCastException here
var settingsHelper = kernel.Get<ISettingsHelper>();
var messenger = kernel.Get<INetworkMessenger>();
var factory = kernel.Get<IBuildServerFactory>();
var dialogs = kernel.Get<ICommonDialogs>();
因此,显然是IProcessHelper实现有问题——再次:
// resolve ProcessHelper dependencies:
var processWrapper = kernel.Get<IProcessWrapper>();
var wmiWrapper = kernel.Get<IWindowsManagementInstrumentationWrapper>();
var helper = new ProcessHelper(processWrapper, wmiWrapper, logProvider, 300);
现在我再也拿不到InvalidCastException
了。
以下是有问题的类的构造函数和字段:
private readonly ILogProvider _logProvider;
private readonly IProcessWrapper _process;
private readonly IWindowsManagementInstrumentationWrapper _wmi;
public int TimeoutSeconds { get; private set; }
public ProcessHelper(IProcessWrapper process,
IWindowsManagementInstrumentationWrapper wmiWrapper,
ILogProvider logProvider,
int timeout)
{
_logProvider = logProvider;
_process = process;
_wmi = wmiWrapper;
TimeoutSeconds = timeout;
}
以及NinjectModule如何绑定它:
Bind<IProcessHelper>().To<ProcessHelper>()
.WithConstructorArgument("timeout", Properties.Settings.Default.ProcessTimeoutSeconds);
**重新编辑**
在@jure评论的帮助下,我发现Properties.Settings.Default
中ProcessTimeoutSeconds
的类型实际上被设置为string
,而它显然想要int
。加油!
在向WithConstructorArguments
设置传递常数值时,需要确保对象的类型对于实现类构造函数参数有效。
正如您后来发现的,您在设置中传递string
对象作为构造函数参数,但构造函数需要int
。这给了你InvalidCastException。
顺便说一句,如果Ninject给你一些更好的异常,那就太好了,这确实很难调试。