使用Autofac注入特定接口实例

3
我是一个有用的助手,可以为您翻译中文。
我有一个控制器,它接收了一个特定的接口实例。
这个接口看起来像这样:
public interface IMyInterface
{
   ... implementation goes here
}

然后我有一些类实现了这个接口,就像这样:

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

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

在我的ControllerA中,我有以下构造函数:
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

IIRC:

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

更新

好的。我误读了你的问题。

实际上,你绝不能做你所要求的事情。这必然会给你带来问题。为什么呢?因为没有办法确定控制器是否能够使用相同的接口。你打破了Liskov替换原则等原则。现在可能不是问题,但让你的应用程序增长并在一年后回来,尝试理解为什么它不起作用。

相反,创建两个新接口,这些接口派生自`IMyInterface´,并在控制器中请求它们。

更新2

引用snowbear的话:

我不同意。OP 没有说他的控制器不能与另一个类型的实例一起工作,他说他想在不同的控制器中注入不同类型的实例。让我们想象他有一些服务来提取数据,他有一个服务包装了这个数据服务并提供缓存功能。在这种情况下,我认为它们应该具有相同的接口,并且这是DI注入正确服务的问题。

OP 就是这样说的:控制器A不能与控制器B使用相同的类。否则,他为什么要在相同的接口下在不同的控制器中获取不同的类呢?

Brendan:

个人而言,我会创建一个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)
{
}

它怎么知道它是为ControllberB而设计的?ControllerA和ControllerB看起来一样,但它们只是针对IMyInterface有不同的实现。 - Brendan Vogt
@jgauffin,我不同意。 OP并没有说他的控制器不能与另一种类型的实例一起工作,而是说他想注入不同类型的实例。让我们想象他有一个提取数据的服务,并且他有一个包装此数据服务并提供缓存功能的服务。在这种情况下,我认为它们应该具有相同的接口,并且正确的服务应该通过DI来注入。 - Snowbear
@jgauffin + @Snowbear:请查看我的更新帖子,然后告诉我接下来该怎么办?谢谢。 - Brendan Vogt
@jgauffin:我打算创建一个INewsMapper。感谢建议。那么我需要为每个映射器创建一个接口吗? - Brendan Vogt
@jgauffin,对于使用泛型的解决方案我也给予了赞同。但是总的来说,我仍然相信在某些情况下,你可能会有多个实现相同接口的情况,并且希望在不创建标记接口的情况下注入它们。 - Snowbear
@Brendan:如果你选择通用版本,就不必为每个映射器创建一个接口了。@Snowbear:如果这对你有效,那就好 :) - jgauffin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接