2017-04-24 3 views
0

私は工場バインディングをNinjectなどのオブジェクトに注入しています。NinjectはReactiveUIへのアップグレード後に暗黙的な自己バインディングのために複数のバインディングを見つけています。7.2

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

は、我々は

var newDoc = DocumentFactory() 

DocumentFactoryのへの最初の呼び出し()が成功したようにそれを呼び出します。

Ninjectは、アクティブ化時点でTNewDocumentに複数のバインディングがあると報告します。

enter image description here

私の代わりに工場を使用してのカーネルを直接呼び出すために私のコードを変更しました。私は、私が実際にGetAll呼び出しから返されるオブジェクトの数をチェック

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

をしました。この番号は、新しいオブジェクトを作成するたびに増加します。

最初に1つのオブジェクトが返されます。 2回目のオブジェクト、3回目の3回など。

私たちはgitを使ってリポジトリを二等分し、改ざんの変化を発見しました。それはReactiveUI 7.1 to 7.2からのアップグレードでした。ナゲットの変更以外のコードの変更は他にありませんでした。

しかし、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

私は

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

     } 
    } 

でデフォルトReactiveUIビューロケータをオーバーライドし、初期化が今

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); 
    } 
です
関連する問題