Как привязать один экземпляр singleton в ninject к нескольким методам привязки

Используя инфраструктуру MVVM вместе с Ninject, у меня есть разные конкретные классы ViewModel, привязанные к интерфейсу IViewModel. Моя проблема заключается в том, что мне нужна некоторая гибкость в том, как определить, какая ViewModel внедряется в представление. Я хочу иметь возможность использовать атрибут Named(string), ConstraintAttribute или базовый Attribute для определения правильной ViewModel.

Или, другими словами, я хочу, чтобы все они возвращали одноэлементный экземпляр AlphaViewModel:

Bind<IViewModel>().To<AlphaViewModel>().WhenTargetHas<AlphaAttribute>();
Bind<IViewModel>().To<AlphaViewModel>().WhenMemberHas<AlphaAttribute>();
Bind<IViewModel>().To<AlphaViewModel>().WhenClassHas<AlphaAttribute>();

Bind<IViewModel>().To<AlphaViewModel>().Named("Alpha");

Bind<IViewModel>().To<AlphaViewModel>().WhenInjectedInto<AlphaView>();

я пробовал

A) Bind<IViewModel>().To<AlphaViewModel>().WhenInjectedInto<AlphaView>().InSingletonScope().Named("Alpha");
B) Bind<IViewModel>().To<AlphaViewModel>().WhenClassHas<AlphaAttribute>().InSingletonScope.Named("Alpha");

и подобные комбинации, но это, кажется, усложняет требования.


A будет иметь правильную инъекцию только в том случае, если его настройка выглядит следующим образом:

public partial class AlphaView : Window
{
    public AlphaView()
    {
        InitializeComponent();
    }
    public AlphaView([Named("Alpha")]IViewModel viewModel) : this()
    {
        DataContext = viewModel;
    }
}

B имеет немного большую свободу действий в том смысле, что представление может быть названо как-то иначе, но для внедрения ViewModel по-прежнему требуются оба параметра:

[AlphaAttribute]
public partial class BravoView : Window
{
    public BravoView()
    {
        InitializeComponent();
    }
    public BravoView([Named("Alpha")]IViewModel viewModel) : this()
    {
        DataContext = viewModel;
    }
}


Когда я хочу иметь возможность внедрить одноэлементную AlphaViewModel, используя любой из атрибутов или имен, чтобы можно было использовать все 3 экземпляра и указывать на одну и ту же ViewModel.

[AlphaAttribute]
public partial class CharlieView : Window
{
    public CharlieView()
    {
        InitializeComponent();
    }
    public CharlieView(IViewModel viewModel) : this()
    {
        DataContext = viewModel;
    }
}

public partial class CharlieView : Window
{
    public CharlieView()
    {
        InitializeComponent();
    }
    public CharlieView([Named("Alpha")]IViewModel viewModel) : this()
    {
        DataContext = viewModel;
    }
}

public partial class CharlieView : Window
{
    public CharlieView()
    {
        InitializeComponent();
    }
    [AlphaAttribute]
    public IViewModel AlphaVM { get; set; }
}

person Ben Gilbert    schedule 26.09.2019    source источник


Ответы (1)


Этого можно достичь, используя единую одноэлементную привязку для AlphaViewModel.

Bind<AlphaViewModel>().ToSelf().InSingletonScope();

И n привязок, «перенаправляющих» запрос на AlphaViewModel, например:

Bind<IViewModel>()
    .ToMethod(ctx => ctx.Kernel.Get<AlphaViewModel>())
    .WhenTargetHas<AlphaAttribute>();

...

Bind<IViewModel>()
    .ToMethod(ctx => ctx.Kernel.Get<AlphaViewModel>())
    .Named("Alpha");
person BatteryBackupUnit    schedule 10.10.2019