Внедрение определенного экземпляра интерфейса с использованием Autofac - PullRequest
3 голосов
/ 14 февраля 2011

У меня есть контроллер, и он получает конкретный экземпляр интерфейса.

Интерфейс выглядит примерно так:

public interface IMyInterface
{
   ... implementation goes here
}

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

public class MyClassA : IMyInterface
{
   ... implementation goes here
}

public class MyClassB : IMyInterface
{
   ... implementation goes here
}

В моем контроллере А у меня есть следующий конструктор:

private ICustomerService customerService;
private IMyInterface myInterface;

puvlic ControllerA(ICustomerService customerService, IMyInterface myInterface)
{
   this.customerService = customerService;
   this.myInterface = myInterface;
}

В моем global.ascx:

protected void Application_Start()
{
   // Autofac
   var builder = new ContainerBuilder();
   builder.RegisterControllers(Assembly.GetExecutingAssembly());
   builder.RegisterType<NewsService>().As<INewsService>();

   IContainer container = builder.Build();
   DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}

Я указал, что Autofac должен предоставить экземпляр ICustomerService. Как бы я указать тип экземпляра для IMyInterface? В этом случае для ControllerA я хотел бы, чтобы Autofac внедрил экземпляр ClassA. И для ControllerB я хотел бы, чтобы это внедрило ClassB. Как бы я это сделал?

ОБНОВЛЕНО 2011-02-14:

Позвольте мне рассказать вам о моей реальной жизненной ситуации. У меня есть NewsController, конструктор которого выглядит так:

public NewsController(INewsService newsService, IMapper newsMapper)
{
   Check.Argument.IsNotNull(newsService, "newsService");
   Check.Argument.IsNotNull(newsMapper, "newsMapper");

   this.newsService = newsService;
   this.newsMapper = newsMapper;
}

Интерфейс IMapper:

public interface IMapper
{
   object Map(object source, Type sourceType, Type destinationType);
}

Я использую AutoMapper. Так что мой NewsMapper будет выглядеть так:

public class NewsMapper : IMapper
{
   static NewsMapper()
   {
      Mapper.CreateMap<News, NewsEditViewData>();
      Mapper.CreateMap<NewsEditViewData, News>();
   }

   public object Map(object source, Type sourceType, Type destinationType)
   {
      return Mapper.Map(source, sourceType, destinationType);
   }
}

Так как бы вы порекомендовали мне сделать это сейчас?

1 Ответ

5 голосов
/ 14 февраля 2011

IIRC:

builder.RegisterType<MyClassB>().As<IMyInterface>()

Обновление

Ok. Не правильно прочитал ваш вопрос.

На самом деле, вы никогда не должны делать то, что просите. Это должно доставить вам проблемы. Зачем? Поскольку нет способа определить, что контроллеры не могут работать с одним и тем же интерфейсом. Среди прочего вы нарушаете принцип подстановки Лисковых. Возможно, сейчас это не проблема, но пусть ваше приложение будет расти и через год вернуться к нему и попытаться понять, почему оно не работает.

Вместо этого создайте два новых интерфейса, которые являются производными от IMyInterface и запросите их в контроллерах.

Обновление 2

Qouting snowbear:

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

ОП говорит только о том, что: Контроллер A не может работать с тем же классом, что и контроллер B. Почему он иначе хотел бы получить разные классы в разных контроллерах для одного и того же интерфейса?

Брендан:

Я бы лично создал интерфейс INewsMapper, чтобы все было ясно и ясно. Но если вы не хотите этого делать: перейдите к универсальному интерфейсу с агрегированным корнем в качестве параметра типа.

public interface IMapper<T> : IMapper where T : class
{

}

public class NewsMapper : IMapper<News>
{
   static NewsMapper()
   {
      Mapper.CreateMap<News, NewsEditViewData>();
      Mapper.CreateMap<NewsEditViewData, News>();
   }

   public object Map(object source, Type sourceType, Type destinationType)
   {
      return Mapper.Map(source, sourceType, destinationType);
   }
}

public NewsController(INewsService newsService, IMapper<News> newsMapper)
{
}
...