Возможная ошибка с внедрением зависимости на MvvmCross

1

В настоящее время я работаю над кросс-платформой (Android и iOS), используя блестящий MVVMCross, и все идет хорошо с приложением, и никаких серьезных проблем пока нет.

Однако сегодня я ударил один, что вызвало у меня некоторые проблемы. Я твердо верю в разделение проблем, и то, что я пытаюсь сделать, - это зарегистрировать класс как ленивый синглэнд-исполнитель двух разных интерфейсов. Это мой App.cs в PCL:

public class App : Cirrious.MvvmCross.ViewModels.MvxApplication
{
    public override void Initialize()
    {
        CreatableTypes()
            .EndingWith("Service")
            .AsInterfaces()
            .RegisterAsLazySingleton();

        RegisterAppStart<LoginViewModel>();

        Mvx.LazyConstructAndRegisterSingleton<ISystemConfigProviderInitialiser, SystemConfigProvider>();
        Mvx.LazyConstructAndRegisterSingleton<ISystemConfigProvider, SystemConfigProvider>();
    }
}

ISystemConfigProvider будет иметь только несколько свойств только для чтения и будет введен в модели просмотра, которые должны прочитать конфигурацию системы.

ISystemConfigProviderInitializer будет введен в DataService (сам построенный IoC) и имеет метод Initialize(), который позволяет передавать poco, в котором ISystemConfigProvider все свойства, упомянутые для ISystemConfigProvider

Для полноты SystemConfigProvider выглядит так:

public class SystemConfigProvider: ISystemConfigProvider, ISystemConfigProviderInitialiser
{
   public string Name {get;}
   ....
   public string Z {get;}

   public void Initialize(PocoObjToSetPropertiesAbove obj)
   {
      //set all properties
   }

}

Проблема, с которой я сталкиваюсь, заключается в том, что класс SystemConfigProvider создается несколько раз. дважды, по-видимому, один раз за каждый интерфейс, что противоречит тому, что мне рассказано на вики-странице MVVMCross о местоположении службы и инверсии элемента управления:

Техническая нота> ленивая реализация синглтона здесь довольно техническая - она гарантирует, что если класс a реализует IOne и ITwo, то тот же экземпляр будет возвращен при разрешении IOne> и ITwo.

Если я ISystemConfigProviderInitialiser интерфейсом ISystemConfigProviderInitialiser и ISystemConfigProviderInitialiser Initialize() в ISystemConfigProvider и только LazyConstructAndRegisterSingleton интерфейс ISystemConfigProvider то все работает отлично, насколько я могу видеть, но это значит, что все пользователи ISystemConfigProvider теперь могут видеть метод Initialize() что они не должны видеть.

Я бы очень признателен за некоторые советы по этому поводу.

Теги:
xamarin
singleton
inversion-of-control
mvvmcross

1 ответ

2
Лучший ответ

Проблема здесь в том, что контейнер Mvx IoC рассматривает одноэлементный аспект на уровне интерфейса, а не тип экземпляра. Поэтому он не видит, что SystemConfigProvider является одним и тем же типом и должен создавать только один экземпляр.

Чтобы обойти эту проблему, есть несколько вариантов:

1) Просто создайте экземпляр singleton во время инициализации, затем зарегистрируйте этот синглтон для каждого интерфейса:

var provider = Mvx.IocConstruct(SystemConfigProvider);
Mvx.RegisterSingleton<ISystemConfigProviderInitialiser>(provider);
Mvx.RegisterSingleton<ISystemConfigProvider>(provider);

2) Пропустить строитель Func к регистрации

Mvx.RegisterSingleton(() =>
{
    var provider = Mvx.IocConstruct<ISystemConfigProviderInitialiser>();
    return provider;
});

Mvx.RegisterSingleton(() =>
{
    var provider = Mvx.Resolve<ISystemConfigProviderInitialiser>();
    if (provider == null)
    {
        throw new InvalidOperationException("ISystemConfigProviderInitialiser should be resolved first.");
    }
    return (ISystemConfigProvider)provider;
});

Я предполагаю, что инициализатор должен быть разрешен первым, так как существует явный шаг Initialise(), поэтому я генерирую исключение, если оно равно null.

Я думаю, что вариант №1, вероятно, лучше. Это просто и понятно.

Надеюсь это поможет.

  • 0
    Существует также некоторая помощь доступна из RegisterAsLazySingleton - смотрите использование MvxLazySingletonCreator в github.com/MvvmCross/MvvmCross/blob/v3.1/CrossCore/... - так что я думаю , что вы могли бы сделать (new Type [] {typeof(SystemConfigProvider)}).AsInterfaces().RegisterAsLazSingleton() - или мы могли бы добавить IEnmerable который не использовал IEnmerable так сильно.
  • 0
    @slodge Спасибо, ребята, я только что решил использовать вариант 1 выше и создать его сам, а затем зарегистрировать этот экземпляр для обоих интерфейсов. Самое простое и простое решение, чтобы двигаться дальше с этим приложением.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню