在升级到ReactiveUI 7.2之后,Ninject正在为隐式自绑定找到多个绑定

时间:2017-04-24 10:19:45

标签: c# ninject reactiveui

我通过Ninject在像这样的对象上注入了工厂绑定。

[Inject]
public Func<TNewDocument> DocumentFactory { get; set; }

我们称之为

var newDoc = DocumentFactory()

第一次调用DocumentFactory()成功。

后续调用会导致Ninject报告在激活时TNewDocument有多个绑定。

enter image description here

我修改了我的代码以直接调用内核而不是使用工厂。我做了

var docs Kernel.GetAll<TNewDocument>().ToList();
if(docs.Count!=1){
    Console.WriteLine("boo");
}
return docs[0]; // A work around to stop the app crashing

我检查GetAll电话实际返回的对象数量。每次调用以创建新对象时,此数字都会增加。

第一次返回一个对象。第二次是两个对象,第三次是三个等等。

我们将存储库分成两部分以发现重大变化。这是ReactiveUI 7.1 to 7.2的升级版。除了nuget所做的更改之外,没有其他代码更改。

但是ReactiveUI只与Ninject有基本关系。我必须为RxUI提供服务定位器,如下所示。

var customResolver = new FuncDependencyResolver(
    (service, contract) =>
    {
        if (contract != null) return kernel.GetAll(service, contract);
        var items = kernel.GetAll(service);
        var list = items.ToList();
        return list;
    },
    (factory, service, contract) =>
    {
        var binding = kernel.Bind(service).ToMethod(_ => factory());
        if (contract != null) binding.Named(contract);
    });

Locator.Current = customResolver;

除此之外there is no relation

我看不出为什么升级RxUI会导致这个问题。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

这是最新版本中引入的ReactiveUI中的错误/重大更改。

https://github.com/reactiveui/ReactiveUI/pull/1282

我用

覆盖了默认的ReactiveUI View Locator
    /// <summary>
    /// Due to bugs / magic in the ReactiveUI view locator we write our own.
    /// The ReactiveUI view locator causes errors if the ViewModel name
    /// doesn't end with "ViewModel". It ends up thinking the ViewModel
    /// and the View are the same class and then very bad stuff happens.
    /// </summary>
    public class WeinCadViewLocator : IViewLocator
    {
        private readonly IKernel _Kernel;

        public WeinCadViewLocator(IKernel kernel)
        {
            _Kernel = kernel;
        }

        public IViewFor ResolveView<T>(T viewModel, string contract = null) where T : class
        {
            Type generic = typeof(IViewFor<>);
            Type[] args = new[] {viewModel.GetType()};
            var realType = generic.MakeGenericType( args );

            if (contract == null)
            {
                return (IViewFor) _Kernel.Get( realType );

            }
            else
            {
                return (IViewFor) _Kernel.Get( realType, contract );
            }

        }
    }

现在初始化

    public static void Init(IKernel kernel)
    {
        var customResolver = new FuncDependencyResolver
            (
             (service, contract) =>
             {
                 if (contract != null)
                     return kernel.GetAll( service, contract );
                 var items = kernel.GetAll( service );
                 var list = items.ToList();
                 return list;
             }
             , (factory, service, contract) =>
             {
                 var binding = kernel
                      .Bind( service )
                      .ToMethod( _ => factory() );
                 if (contract != null)
                     binding.Named( contract );
             } );


        Locator.CurrentMutable.InitializeSplat();
        Locator.CurrentMutable.InitializeReactiveUI();
        Locator.CurrentMutable = customResolver;
        Locator.CurrentMutable
            .RegisterLazySingleton
              (() => new WeinCadViewLocator(kernel)
              , typeof(IViewLocator));

        var log = SerilogExtensions.DefaultLogger;
        Log.Logger = log;
        SerilogSplatLogger.Register(log);
    }