首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >InvalidCastException at kernel.Get<type>

InvalidCastException at kernel.Get<type>
EN

Stack Overflow用户
提问于 2013-06-27 14:34:43
回答 1查看 995关注 0票数 5

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

由于这一变化,我一直无法启动应用程序,Ninject似乎无法解决应用程序的主要对象(或者它可能是其依赖项之一)。

这个异常让我浪费了大量的时间,而且堆栈跟踪都是Ninject内部的,我不知道在我的代码中应该修复什么,我绑定的方式--现在导致这个异常的类型--最近没有改变:

代码语言:javascript
复制
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方法/ app入口点:

代码语言:javascript
复制
[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,等等)。

通常尼尼姆给非常有用和详细的异常消息-当它是一个ActivationException生命是好的。但是这个InvalidCastException让我不知所措,我不是执行无效转换的那个人,我甚至不知道涉及的是哪些类型。我只知道我可能编写了尼尼微不喜欢的一些代码,也许它与我将IInstaller绑定到它的实现的方式有关,但是如果我注释掉NinjectModule的“分支”部分强制绑定特定的实现(ManualInstaller),它仍然会在这个InvalidCastException中失败。

实现的构造函数:

代码语言:javascript
复制
public ManualInstaller(IView<MainWindowViewModel> view, 
                       IProcessHelper processHelper,
                       ISettingsHelper settingsHelper,
                       ILogProvider logProvider,
                       ISetupBootstrapper installer,
                       bool notifySuccess)
    : base(notifySuccess, processHelper, settingsHelper, logProvider, installer)

相应的绑定代码(其余的依赖项已经绑定,并且没有ActivationException,因此不确定这与我的问题有多相关):

代码语言:javascript
复制
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);

如果还需要什么就让我知道发生了什么。

编辑

单独解决安装程序的依赖关系会产生更多信息:

代码语言:javascript
复制
// 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);

因此,我至少可以将其缩小到我试图解决的类型的特定依赖:问题要么与视图有关,要么与它的唯一依赖关系ViewModel有关。所以我做了这个:

代码语言:javascript
复制
// 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实现是有问题的--同样是:

代码语言:javascript
复制
// resolve ProcessHelper dependencies:
var processWrapper = kernel.Get<IProcessWrapper>();
var wmiWrapper = kernel.Get<IWindowsManagementInstrumentationWrapper>();
var helper = new ProcessHelper(processWrapper, wmiWrapper, logProvider, 300);

现在我再也得不到InvalidCastException了。

下面是有问题的类的构造函数和字段:

代码语言:javascript
复制
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如何绑定它:

代码语言:javascript
复制
Bind<IProcessHelper>().To<ProcessHelper>()
                      .WithConstructorArgument("timeout", Properties.Settings.Default.ProcessTimeoutSeconds);

** RE-编辑**

在@jure的注释的帮助下,我发现Properties.Settings.Default中的Properties.Settings.Default类型实际上被设置为string --显然它想要一个int。开始吧!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-06-27 17:29:42

在向WithConstructorArguments设置传递常量值时,需要确保对象的类型对于实现类构造函数参数是有效的。

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

顺便提一句,如果Ninject给了您一些更好的例外,这确实很难调试。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17346045

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档