2017-04-24 76 views
0

我通過Ninject將工廠綁定注入到類似的對象上。Ninject在升級到ReactiveUI後發現隱式自綁定的多個綁定7.2

[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調用實際返回的對象的數量。每次調用創建一個新對象時,這個數字都會增加。

第一次返回一個對象。第二次兩個對象,第三次三個,等等。

我們git將存儲庫平分以發現重大更改。這是從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會導致此問題。有任何想法嗎?

回答

0

這是在最新版本中引入的ReactiveUI中的一個錯誤/重大更改。

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

我推翻默認ReactiveUI查看定位與

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