C# 内核处的InvalidCastException.Get<;类型>;

C# 内核处的InvalidCastException.Get<;类型>;,c#,wpf,ninject,C#,Wpf,Ninject,我有一个WPF应用程序,它可能用命令行参数启动,也可能不用命令行参数启动。我以前在App.xaml代码中的OnStartup(StartupEventArgs e)方法中有我的合成根,但这导致了应用程序关闭问题,因此我将App.xaml转换为一个“页面”(而不是“应用程序定义”),并编写了我自己的程序类,其中包含我自己的应用程序入口点,这将成为我的新组合根位置 自从那次更改之后,我一直无法启动应用程序,Ninject似乎无法解析应用程序的主要对象(或者它可能是其依赖项之一?) 这个异常让我浪费了

我有一个WPF应用程序,它可能用命令行参数启动,也可能不用命令行参数启动。我以前在App.xaml代码中的
OnStartup(StartupEventArgs e)
方法中有我的合成根,但这导致了应用程序关闭问题,因此我将App.xaml转换为一个“页面”(而不是“应用程序定义”),并编写了我自己的
程序
类,其中包含我自己的应用程序入口点,这将成为我的新组合根位置

自从那次更改之后,我一直无法启动应用程序,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()
Ninject模块根据提供的命令行参数将
IInstaller
绑定到这样或那样的实现(例如,指定
QuietInterfaceArgument
时绑定到
silenInstaller
,未指定时绑定到
ManualInstaller
等)

通常,当Ninject是一个
激活异常时,它会给出非常有用和详细的异常消息。但是这个
InvalidCastException
让我不知所措,我不是执行无效强制转换的人,我甚至不知道所涉及的类型。我只知道我可能写了一些Ninject不喜欢的代码,也许这与我将
IInstaller
绑定到其实现的方式有关,但是如果我注释掉Ninject模块的“分支”部分,强制绑定我要的特定实现(
ManualInstaller
),它仍然会失败,出现此
InvalidCastException

实现的构造函数:

public ManualInstaller(IView<MainWindowViewModel> view, 
                       IProcessHelper processHelper,
                       ISettingsHelper settingsHelper,
                       ILogProvider logProvider,
                       ISetupBootstrapper installer,
                       bool notifySuccess)
    : base(notifySuccess, processHelper, settingsHelper, logProvider, installer)
如果还需要了解发生了什么事,请随时告诉我

编辑

单独解析安装程序的依赖关系可获得更多信息:

// 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);
以及模块如何绑定它:

Bind<IProcessHelper>().To<ProcessHelper>()
                      .WithConstructorArgument("timeout", Properties.Settings.Default.ProcessTimeoutSeconds);
Bind().To())
.WithConstructorArgument(“timeout”、Properties.Settings.Default.ProcessTimeoutSeconds);
**重新编辑**


借助@jure的评论,我发现
Properties.Settings.Default
中的
ProcessTimeoutSeconds
的类型实际上设置为
string
——显然它需要
int
。加油

当您使用ConstructorArguments向
设置传递常量值时,您需要确保对象的类型对于实现类构造函数参数有效

正如您后来发现的那样,您在设置中将
string
对象作为构造函数参数传递,但构造函数需要
int
。这给了你


顺便说一句,如果Ninject给了您一些更好的异常,那就太好了,这确实很难调试。

只是猜测,可能绑定设置中的一些构造函数参数不是预期的类型。。WithConstructorArgument无法检查传递给它的对象是否是构造函数参数的有效类型。这可能是无效卡斯特例外的根源。您应该检查“msg”和“notifySuccess”对象是否对MainWindowViewModel和ManualInstaller构造函数有效。@jure bang on(请参阅重新编辑),您猜在我发布第一次编辑之前。。。你是个明星!把它作为一个答案贴出来,我很乐意投赞成票并接受它!很高兴你找到了问题的原因……我发布了答案,而且我绑定它的方式也改变了;在重构过程中,我将应用程序设置移动到了“MyApp.Core”程序集,并且一定忘记了将该设置的默认
String
类型更改为
int
// 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);
// 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>();
// resolve ProcessHelper dependencies:
var processWrapper = kernel.Get<IProcessWrapper>();
var wmiWrapper = kernel.Get<IWindowsManagementInstrumentationWrapper>();
var helper = new ProcessHelper(processWrapper, wmiWrapper, logProvider, 300);
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;
}
Bind<IProcessHelper>().To<ProcessHelper>()
                      .WithConstructorArgument("timeout", Properties.Settings.Default.ProcessTimeoutSeconds);