Подтвердить что ты не робот

Unity Зарегистрируйте два интерфейса как один синглтон

как зарегистрировать два разных интерфейса в Unity с одним и тем же экземпляром... В настоящее время я использую

        _container.RegisterType<EventService, EventService>(new ContainerControlledLifetimeManager());
        _container.RegisterInstance<IEventService>(_container.Resolve<EventService>());
        _container.RegisterInstance<IEventServiceInformation>(_container.Resolve<EventService>());

который работает, но выглядит не очень хорошо.

Итак, я думаю, вы поняли. EventService реализует два интерфейса, я хочу ссылку на один и тот же объект, если я разрешаю интерфейсы.

Крис

4b9b3361

Ответ 1

Edit

После некоторой обратной связи в комментариях я решил, что ответ Свена - отличный ответ. Спасибо Крису Таваресу за указание технических достоинств.


Это почти единственный способ сделать это.

Вы можете немного изменить его (я ненавижу RegisterType с тем же типом для каждого общего параметра):

EventService es = _container.Resolve<EventService>();
_container.RegisterInstance<IEventService>(es);
_container.RegisterInstance<IEventServiceInformation>(es);

Если один или несколько ваших детей IoC запросят конкретный тип EventService (надеюсь, что нет), вы добавите еще один RegisterInstance типа RegisterInstance<EventService>. Надеюсь, вам это не понадобится, и все зависимые объекты запрашивают IEventService, а не EventService.

Надеюсь, это поможет, Андерсон

Ответ 2

[2nd Edit]

Из-за серьезных изменений в способах, которыми Unity обрабатывает регистрации, обновленный подход больше не работает. [Оригинальный ответ] - это путь, по которому нужно идти снова. (Для более подробной информации об изменениях в Unity, пожалуйста, обратитесь к ссылке, приведенной в комментариях ниже.)

[Редактировать]

Решение для этого через конфигурацию XML можно найти здесь. Основываясь на этом ответе, я бы предложил оптимизированный подход только к коду:

_container.RegisterType<IEventService, EventService>(new ContainerControlledLifetimeManager());
_container.RegisterType<IEventServiceInformation, EventService>(new ContainerControlledLifetimeManager());
bool singleton = ReferenceEquals(_container.Resolve<IEventService>(), _container.Resolve<IEventServiceInformation>());

Таким образом, сам класс EventService не публикуется контейнером. Поскольку класс должен рассматриваться как деталь реализации, это предпочтительный подход.

[Оригинальный ответ]

Немного опоздал с ответом, но должен сделать свое дело:

_container.RegisterType<EventService>(new ContainerControlledLifetimeManager());
_container.RegisterType<IEventService, EventService>();
_container.RegisterType<IEventServiceInformation, EventService>();

bool singleton = ReferenceEquals(_container.Resolve<IEventService>(), _container.Resolve<IEventServiceInformation>());

Ответ 3

Адаптивный подход казался громоздким для такой простой вещи, поэтому я посмотрел немного дальше. Чтобы обойти проблему с именованными экземплярами, вам необходимо зарегистрировать тип и зарегистрировать фабрики для интерфейсов.

 InjectionFactory factory = new InjectionFactory(x => x.Resolve<SimulationService>());
 this.Container.RegisterType<SimulationService>(new ContainerControlledLifetimeManager());
 this.Container.RegisterType<IContentProvider>("SimulationContentProvider", factory);
 this.Container.RegisterType<ISimulationService>(factory);

Таким образом, вам не нужно создавать экземпляр конкретного класса (при регистрации), что было невозможно в моем случае из-за отсутствия зависимостей.

Ответ 4

Одним из решений, которое также может работать для именованных экземпляров, является использование шаблона адаптера для создания переходных адаптеров для интерфейса, который обтекает экземпляры singleton. Затем разрешенные экземпляры всегда будут направлены на экземпляр singleton, событие, если они разрешены с помощью ResolveAll. Это помогает при наличии кучи сервисов, реализующих общий интерфейс, такой как IStartable или что-то в этом роде.

public class EventServiceAdapter<T> : IEventService where T : IEventService
{
    private readonly T _adapted;
    EventServiceAdapter(T adapted)
    {
        _adapted = adapted;
    }
    public string SomeMethod()
    {
         return _adapted.SomeMethod();
    }
} 

Затем зарегистрируйте адаптер интерфейса вокруг зарегистрированного одноэлементного типа.

_container
    .RegisterType<EventService>(new ContainerControlledLifetimeManager())
    .RegisterType<IEventService, EventServiceAdapter<EventService>>("namedEventService");

Затем вы можете скрыть любой синглтон за любым количеством интерфейсов и работать с помощью как Resolve, так и ResolveAll.

Ответ 5

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

_container.RegisterType<EventService>(TypeLifetime.Singleton); <- This could be an instance
_container.RegisterType<IEventService, EventService>();
_container.RegisterType<IOtherEventService, EventService>();

Вам необходимо зарегистрировать синглтон и все сопоставления с ним отдельно. Unity v6 будет иметь метод регистрации, чтобы сделать все это сразу.