在视图模型中调用异步方法时,Simple Injector 在 Caliburn.Micro Bootstrapper.Buildup 中引发错误

问题描述

我正在尝试使用 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 仍然会抛出异常。

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

我完整的 Bootstrapper 配置文件如下所示:

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.Configure 中添加 SequentialResult 时,如下所示。

protected override void Configure()
{
    _container.Register<IWindowManager,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 消息=配置无效。创造 SequentialResult 类型的实例失败。类型的构造函数 SequentialResult 包含名称为“enumerator”的参数和 输入 IEnumerator,但 IEnumerator注册。 要解析 IEnumerator,必须在 容器。 Source=SimpleInjector StackTrace: at SimpleInjector.InstanceProducer.VerifyExpressionBuilding() 在 SimpleInjector.Container.VerifyThatAllExpressionsCanBeBuilt(InstanceProducer[] producerToVerify)在 SimpleInjector.Container.VerifyThatAllExpressionsCanBeBuilt() 在 SimpleInjector.Container.VerifyInternal(Boolean 抑制LifestyleMismatchVerification)在 SimpleInjector.Container.Verify(Verificationoption option) 在 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 此外,标记解决方案的内容在我的代码示例中似乎不起作用。

解决方法

@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);
//}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...