【问题标题】:Simple Injector throws an error in Caliburn.Micro Bootstrapper.Buildup when calling async method in the viewmodel在视图模型中调用异步方法时,Simple Injector 在 Caliburn.Micro Bootstrapper.Buildup 中引发错误
【发布时间】:2021-05-14 05:28:06
【问题描述】:

我正在尝试使用 Simple Injector 作为 Caliburn.Micro 的 DI 容器。演示来源:https://github.com/nvstrien/WPFDemos

这个项目有一个基本的 Caliburn.Micro 设置和一个简单的注射器容器。 ShellView 有 1 个按钮,按下时会调用异步方法来获取一些模拟数据。

我在 Bootstrapper.Buildup 中收到此错误。

SimpleInjector.ActivationException: '找不到类型 SequentialResult 的注册。确保 SequentialResult 已注册,例如通过调用 'Container.Register();'在注册阶段。无法进行隐式注册,因为 Container.Options.ResolveUnregisteredConcreteTypes 设置为“false”,现在这是 v5 中的默认设置。这不允许容器构造这个未注册的具体类型。有关为什么现在默认不允许解析未注册的具体类型以及您可以应用哪些可能的修复程序的更多信息,请参阅https://simpleinjector.org/ructd。 '

这里建议注释掉 Bootstrapper.BuildUp 应该可以工作:Caliburn.Micro Bootstrapper 'BuildUp' method throws exception when Simple Injector is used

但是,这样做时,SimpleInjector 仍然会抛出异常。

任何解决此问题的帮助将不胜感激

我完整的引导程序配置文件如下所示:

public static readonly Container _container = new();

public Bootstrapper()
{
    Initialize();
}

protected override void Configure()
{
    _container.Register<IWindowManager, WindowManager>();
    _container.RegisterSingleton<IEventAggregator, EventAggregator>();

    GetType().Assembly.GetTypes()
        .Where(type => type.IsClass)
        .Where(type => type.Name.EndsWith("ViewModel"))
        .ToList()
        .ForEach(viewModelType => _container.RegisterSingleton(viewModelType, viewModelType));

    _container.Verify();
}

protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
{
    DisplayRootViewFor<ShellViewModel>();
}

protected override IEnumerable<object> GetAllInstances(Type service)
{
    // as discussed here: https://stackoverflow.com/questions/32258863/simple-injector-getallinstances-throwing-exception-with-caliburn-micro

    //_container.GetAllInstances(service);

    IServiceProvider provider = _container;

    Type collectionType = typeof(IEnumerable<>).MakeGenericType(service);

    IEnumerable<object> services = (IEnumerable<object>)provider.GetService(collectionType);

    return services ?? Enumerable.Empty<object>();
}

protected override object GetInstance(System.Type service, string key)
{
    return _container.GetInstance(service);
}

protected override IEnumerable<Assembly> SelectAssemblies()
{
    return new[] { Assembly.GetExecutingAssembly() };
}

// see: https://stackoverflow.com/questions/37631468/caliburn-micro-bootstrapper-buildup-method-throws-exception-when-simple-inject
// commenting out BuildUp still throws an exception in SimpleInjector.dll 
protected override void BuildUp(object instance)
{
    InstanceProducer registration = _container.GetRegistration(instance.GetType(), true);
    registration.Registration.InitializeInstance(instance);
}

在 ShellViewModel 中,我有 1 个方法在按下 ShellView 上的按钮时运行。

public async Task Button1()
{
    Debug.Print("Hello world");

    var data = await GetSampleDataAsync();

    foreach (var item in data)
    {
        Debug.Print(item);
    }
}

public async Task<IEnumerable<string>> GetSampleDataAsync()
{
    // method simulating getting async data
    var data = new List<string>() { "hello", "world" };

    return await Task.FromResult(data);
}

当调用 'await GetSampleDataAsync()' 时发生错误。

在Bootstrapper中添加SequentialResult时。配置如下。

protected override void Configure()
{
    _container.Register<IWindowManager, WindowManager>();
    _container.RegisterSingleton<IEventAggregator, EventAggregator>();
    _container.Register<SequentialResult>();

    GetType().Assembly.GetTypes()
        .Where(type => type.IsClass)
        .Where(type => type.Name.EndsWith("ViewModel"))
        .ToList()
        .ForEach(viewModelType => _container.RegisterSingleton(viewModelType, viewModelType));

    _container.Verify();
}

我得到下一个错误:

System.InvalidOperationException
HResult=0x80131509 Message=配置无效。创造 SequentialResult 类型的实例失败。类型的构造函数 SequentialResult 包含名称为“enumerator”的参数和 类型 IEnumerator,但未注册 IEnumerator。 要解析 IEnumerator,它必须在 容器。 Source=SimpleInjector StackTrace:在 SimpleInjector.InstanceProducer.VerifyExpressionBuilding() 在 SimpleInjector.Container.VerifyThatAllExpressionsCanBeBuilt(InstanceProducer[] 生产者ToVerify)在 SimpleInjector.Container.VerifyThatAllExpressionsCanBeBuilt() 在 SimpleInjector.Container.VerifyInternal(布尔 抑制LifestyleMismatchVerification)在 SimpleInjector.Container.Verify(VerificationOption 选项) 在 SimpleInjector.Container.Verify() 在 CaliburnMicroWithSimpleInjectorDemo.Bootstrapper.Configure() 在 C:\Users\Niels\source\repos\WPFDemos\CaliburnMicroWithSimpleInjectorDemo\Bootstrapper.cs:line 37 在 Caliburn.Micro.BootstrapperBase.StartRuntime() 在 Caliburn.Micro.BootstrapperBase.Initialize() 在 CaliburnMicroWithSimpleInjectorDemo.Bootstrapper..ctor() 在 C:\Users\Niels\source\repos\WPFDemos\CaliburnMicroWithSimpleInjectorDemo\Bootstrapper.cs:line 22

此异常最初是在此调用堆栈中引发的: [外部代码]

内部异常1:ActivationException:类型的构造函数 SequentialResult 包含名称为“enumerator”的参数和 类型 IEnumerator,但未注册 IEnumerator。 要解析 IEnumerator,它必须在 容器。

当我将 ShellViewModel 中的方法更改为像这样同步时,我没有收到任何异常:

public void Button1()
{
    Debug.Print("Hello world");

    var data = GetSampleData();

    foreach (var item in data)
    {
        Debug.Print(item);
    }
}

public IEnumerable<string> GetSampleData()
{
    var data = new List<string>() { "hello", "world" };
    return data;
}

在我看来,容器没有得到正确配置,无法与 Caliburn.Micro 中的某些实现一起使用,但 Bootstrapper 配置遵循推荐的路径。不幸的是,我无法理解这里的解释:Caliburn.Micro Bootstrapper 'BuildUp' method throws exception when Simple Injector is used 另外,标记为解决方案的内容在我的代码示例中似乎不起作用。

【问题讨论】:

  • 你能添加一个最小的、可重现的例子来演示这个问题吗?
  • 我在问题中包含了一个 - 你可以在这里找到它 演示源:github.com/nvstrien/WPFDemos 如果您对此演示有任何疑问,请告诉我。谢谢。
  • 请将其包含在您的 SO 问题中。
  • 我不确定我是否理解 - 演示网址位于我的 SO 问题的第二行。对不起,如果我犯了一个新手错误(我是新手)
  • 我现在明白了我应该在我的帖子中做得更好的地方。我现在已经添加了配置容器的 Bootstrapper 配置代码。我还添加了调用时导致异常的 ShellViewModel 的代码。我希望这更清楚。我在 github 上的示例项目是我能想到的带有 Simple-Inject 的 .Net 5 Caliburn.Micro 最简单的示例。

标签: dependency-injection caliburn.micro .net-5 simple-injector


【解决方案1】:

@Steven:注释掉 BuildUp 确实解决了我的问题。

我认为在来 SO 询问我的问题之前,我已经在示例项目中测试了将 BuildUp 注释掉,但现在再次尝试解决了我的问题。感谢您让我重回正轨!

解决方案:注释掉/删除 BootStrapper.BuildUp,这里也建议:Caliburn.Micro Bootstrapper 'BuildUp' method throws exception when Simple Injector is used

//protected override void BuildUp(object instance)
//{
//    InstanceProducer registration = _container.GetRegistration(instance.GetType(), true);
//    registration.Registration.InitializeInstance(instance);
//}

【讨论】:

    猜你喜欢
    • 2016-10-04
    • 1970-01-01
    • 2020-02-10
    • 1970-01-01
    • 1970-01-01
    • 2016-07-02
    • 1970-01-01
    • 2020-11-04
    • 1970-01-01
    相关资源
    最近更新 更多