Как зарезервировать использование зарегистрированного сервиса с передачей параметров в конструкторе? - PullRequest
1 голос
/ 20 января 2020

Я новичок ie до OOP и IO C контейнер. Мне нужно понять, как использовать инъекцию зависимости. Простая структура моего приложения выглядит следующим образом.

Код ниже принадлежит CacheService:

using Akavache;

    public class CacheService : ICacheService
    {
        protected IBlobCache Cache;

        public CacheService(IBlobCache blobCache, string applicationName)
        {
            Cache = blobCache;
            BlobCache.ApplicationName = applicationName;
        }
    }

Я зарегистрировал этот сервис, как показано ниже в App.cs, потому что мне нужно использовать тот же сервис с 2 различных типа.

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
    containerRegistry.RegisterSingleton<IMockApiService, MockApiService>();
    containerRegistry.RegisterSingleton<IEssentialsService, EssentialsService>();

    containerRegistry.RegisterInstance<CacheService>(new CacheService(BlobCache.LocalMachine, "MyAppName"), "LocalMachineCache");
    containerRegistry.RegisterInstance<CacheService>(new CacheService(BlobCache.UserAccount, "MyAppName"), "UserAccountCache");
}

Мой код ViewModel, как показано ниже:

public class SettingsPageViewModel : BindableBase
{
    protected ICacheService CacheService { get; private set; }

    public SettingsPageViewModel(ICacheService cacheService)
    {
        CacheService = cacheService;
    }
}

Возможно ли использование выше или нет? Если это возможно, как я должен изменить свою структуру? Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 22 января 2020

Это можно сделать при регистрации:

Адаптировано из документов :

container.Register<SettingsPageViewModel>(made: Made.Of(() => new SettingsPageViewModel(Arg.Of<ICacheService>("LocalMachineCache"))));

Как правило, вы хотите избежать такого рода вещей, потому что вышеупомянутая регистрация довольно трепетная и неуклюжая. Кроме того, я просто предполагаю , что страница настроек должна получить LocalMachineCache , потому что DryIo c не хочет угадывать, вы получаете ошибку.

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

1 голос
/ 20 января 2020

Насколько я могу судить, такое использование не возможно, поскольку ваш контейнер Io C не знает, как разрешить ICacheService, поскольку вы зарегистрировали экземпляры как CacheService. Когда DryIo c пытается разрешить SettingsPageViewModel, он встречает ICacheService и обнаруживает, что тип не зарегистрирован. По крайней мере, так ведет себя контейнер Unity .

В любом случае, даже , если вы зарегистрировали "LocalMachineCache" и "UserAccountCache" как ICacheService Я сомневаюсь, что это ' d работает, поскольку для DryIo c не будет никакого способа узнать, какой из них будет использоваться с SettingsPageViewModel, поэтому вам придется определить, какой из них разрешить.

Согласно документации, Prism разрешает зависимости по имени соответствующего параметра (если я не понял это неправильно, см. Здесь ). Предполагая, что вам нужен кэш локального компьютера в ваших настройках, вы можете зарегистрировать его как "localMachineCache" (переименовать в соответствии с общими C# соглашениями кодирования в конструкторе SettingsPageViewModel) и присвоить параметру то самое имя

containerRegistry.RegisterInstance<ICacheService>(new CacheService(BlobCache.LocalMachine, "MyAppName"), "localMachineCache");
containerRegistry.RegisterInstance<ICacheService>(new CacheService(BlobCache.UserAccount, "MyAppName"), "userAccountCache");
public SettingsPageViewModel(ICacheService localMachineCache)
{
    CacheService = localMachineCache;
}

И соответственно, если вам нужны оба

public SettingsPageViewModel(ICacheService localMachineCache, ICacheService userAccountCache)
{
    MachineCacheService = localMachineCache;
    UserAccountCacheService = userAccountCache;
}

Edit

Несмотря на то, что это написано в документации, именованные сервисы, похоже, не работают так, как документация состояний. Однако, в зависимости от выбора контейнера Io C, все еще возможно вводить сервисы по их именам.

DryIo c

С параметром made IContainer.Register вы можете указать фабричная функция для создания экземпляров указанного типа. Поскольку Prism помещает абстракцию Io C в используемую платформу, сначала вам нужно получить экземпляр DryIo c IContainer

var container = ((DryIocContainerExtension)containerRegistry).Instance;

, теперь вы можете указать, как создавать экземпляры * 1044. * с

container.Register(Made.Of(
    () => new SettingsPageViewModel(Arg.Of<ICacheService>("LocalMachineCache"))));

Строка, переданная Arg.Of, является служебным ключом, служба зарегистрирована и сообщает DryIoc какой ICacheService разрешить ( обратите внимание , что Я использовал ваше оригинальное имя).

Unity

При единстве есть как минимум два способа добиться этого. Первый - получить экземпляр через UnityContainerExtension (аналог версии DryIo c) и использовать RegisterFactory

unityContainer.RegisterFactory<SettingsPageViewModel>(
    container => new SettingsPageViewModel(container.Resolve<ICacheService>("LocalMachineCache")));

Другой вариант - добавить DependencyAttribute к параметрам конструктора. модели представления

public SettingsPageViewModel([Unity.Dependency("LocalMachineCache")] ICacheService localMachineCache)
{
    CacheService = localMachineCache;
}
...