ReactiveUI依赖注入构造函数

时间:2015-09-18 08:32:23

标签: c# reactiveui splat

我在ReactiveUI中使用内置依赖注入器/ splat注入器。

我有构造函数,我想传递它们适用的数据存储库。

在其他框架中,它只使用与接口的反射,并使用GetServices调用来满足这些构造函数的要求。例如,目前我有这个辅助扩展方法来创建我的类:

        dependencyResolver.Register(() => new SetupFlightViewModel(dependencyResolver.GetService<IScreen>(), dependencyResolver.GetService<IFlightsModel>(), dependencyResolver.GetService<IAirportsModel>()), typeof(ISetupFlightViewModel));

我使用该帮助程序类的原因是为了避免在AppBootStrapper中执行以下操作:

{{1}}

只需检查以确保我没有使用Splat / ReactiveUI框架做任何不明显的事情,而且已经提供了。我意识到执行上述操作会产生性能成本,并且可能会使用Expression Tree编译的表达式来避免每次或某些事件的反射成本。

感谢您的帮助, 格伦

3 个答案:

答案 0 :(得分:4)

Splat依赖解析器(服务注册表)是开箱即用的基础,它不提供依赖注入(DI)。

但是如果你喜欢DI(不是每个人都这样做,因为它可以隐藏依赖关系和设计复杂性,有些人喜欢感受到更好的避免它的痛苦),你可以轻松地将DI插入其中,就像你刚才那样。

关于你的impl的一个评论,我建议你延迟实际调用GetService直到创建对象(如果你的服务注册表内容随着时间的推移而变化,并避免强制{{1} } ordered),例如:

Register

答案 1 :(得分:0)

我刚开始使用 ReactiveUI 并试图做同样的事情。我在 StackOverflow 上找到了这篇文章并找到了解决方案。在充实了一点之后,我想我会分享我的代码。由于这是我搜索中出现的第一个结果,我想我会在这里发布结果,这样任何遵循相同路径的人都可以从我的劳动成果中受益。

public static class Bootstrapper
{
    public static void RegisterDependencies()
    {
        Locator.CurrentMutable.RegisterLazySingleton<ISettingsService>(CreateWithConstructorInjection<InMemorySettingsService>);
        Locator.CurrentMutable.Register<MainWindowViewModel>(CreateWithConstructorInjection<MainWindowViewModel>);
    }

    private static T CreateWithConstructorInjection<T>() where T : class
    {
        // Must be at most one constructor
        ConstructorInfo[] constructors = typeof(T).GetConstructors();
        if (constructors.Count() > 1)
            throw new InvalidOperationException($"Unable to create required dependency for {typeof(T).FullName}: type can not have more than one constructor, found {constructors.Count()}");

        // must not be null
        IEnumerable<Type> types = constructors.Single().GetParameters().Select(p => p.ParameterType).ToArray();
        if (Activator.CreateInstance(typeof(T), types.Select(GetService).ToArray()) is T t)
            return t;

        throw new InvalidOperationException($"Unable to create required dependency of type {typeof(T).FullName}: Activator.CreateInstance() returned null");
    }

    private static object GetService(Type type)
    {
        if (Locator.Current.GetService(type) is Object obj)
            return obj;

        throw new InvalidOperationException($"Unable to create required dependency of type {type.FullName}: IReadonlyDependencyResolver.GetService() returned null");
    }
}

答案 2 :(得分:0)

我为 Splat 编写了一个官方的 NuGet 包,可以进行构造函数注入。

它被称为 Splat.DependencyInjection.SourceGenerator。

它使用源代码生成来查找类的正确依赖项并将它们注入到构造函数中。还支持属性注入。

https://github.com/reactivemarbles/Splat.DI.SourceGenerator