使用 Autofac 注入接口的特定实例

发布于 2024-10-17 09:42:22 字数 2145 浏览 4 评论 0原文

我有一个控制器,它接收接口的特定实例。

该接口看起来像这样:

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);
   }
}

那么您现在建议我如何执行此操作?

I have a controller and it receives a specific instance of an interface.

The interface looks something like this:

public interface IMyInterface
{
   ... implementation goes here
}

And then I have some classes that implement this interface like this:

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

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

In my ControllerA I have the following constructor:

private ICustomerService customerService;
private IMyInterface myInterface;

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

In my 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));
}

I specified that Autofac must supply the instance of ICustomerService. How would I specify the instance type for IMyInterface? In this case for ControllerA I would like Autofac to inject a ClassA instance. And for ControllerB I would like it to inject ClassB. How would I do this?

UPDATED 2011-02-14:

Let me give you my real life situation. I have a NewsController whose constructor looks like this:

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

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

IMapper interface:

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

I'm using AutoMapper. So my NewsMapper will look like this:

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);
   }
}

So how would you recommend me do this now?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无言温柔 2024-10-24 09:42:22

IIRC:

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

更新

好。误读了你的问题。

事实上,你永远不应该做你所要求的事情。它必然会给你带来麻烦。为什么?因为没有办法确定控制器不能使用相同的接口。其中,你违反了里氏替代原则。现在这对您来说可能不是问题,但是让您的应用程序成长并在一年后恢复,并尝试了解它为什么不起作用。

相反,创建两个派生自“IMyInterface”的新接口并在控制器中请求这些接口。

更新 2

引用雪熊:

我不同意。 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)
{
}

IIRC:

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

Update

Ok. Misread your question.

Actually, you should never ever do what you are asking. It's bound to give you problems. Why? Since there is no way to determine that the controllers can not work with the same interface. Amongst others, you are breaking the Liskovs Substitution Principle. It might not be a problem for you now, but let your application grow and come back in a year and try to understand why it isn't working.

Instead, create two new interfaces which derive from `IMyInterface´ and request those in the controllers.

Update 2

Qouting snowbear:

I disagree. OP doesn't says that his
controller cannot work with instance
of another type, he says that he wants
to inject instances of different
types. Let's imagine he has some
service to extract data and he has a
service which wraps this data service
and provides caching functionality. I
believe they should have the same
interface in such situation and it is
matter of DI to inject correct service

OP says just that: Controller A cannot work same class as controller B. Why would he else want to get different classes in different controllers for the same interface?

Brendan:

I personally would create a INewsMapper interface to make everything clear and sound. But if you do not want to do that: Go for a generic interface with the aggregate root as type parameter.

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)
{
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文