开发者

Injecting a specific instance of an interface using Autofac

I am using ASP.NET MVC 3 and Autofac for my dependency injection. I am using AutoMapper for my mapping.

I have an IMapper class that I use for all my model view mappings. So any any of my mapping classes can implement this interface. In the controller below the constructor receives an IMapper instance, and in my User controller it might receive a different instance, maybe userMapper. Getting back to the code below, I have a class called NewsMapper and it implements IMapper. How do I setup dependency injection so that this controller must receive an instance of NewsMapper? Please bear in mind that I might have another mapper called UserMapper.

I have the following controller:

public class NewsController
{
   private INewsService newsService;
   private IMapper newsMapper;

   public NewsController(INewsService newsService, IMapper newsMapper)
   {
      if (newsService == null)
      {
         throw new ArgumentNullException("newsService");
      }

      if (newsMapper == null)
      {
     开发者_JS百科    throw new ArgumentNullException("newsMapper");
      }

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

I have the following configuration in my global.asax.cs:

var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<NewsService>().As<INewsService>();
builder.RegisterType<NewsRepository>().As<INewsRepository>();

UPDATED:

My IMapper interface:

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

My NewsMapper class:

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

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

My controller action method where I do the mappings:

[HttpPost]
public ActionResult Create(NewsViewModel newsViewModel)
{
   // Check model state
   if (!ModelState.IsValid)
   {
      return View("Create", newsViewModel);
   }

   // Do mapping
   var news = (News)newsMapper.Map(newsViewModel, typeof(NewsViewModel), typeof(News));

   // Add to database via news service

   // Redirect to list view
   return RedirectToAction("List", "News");
}


The problem here is the broadness of the IMapper contract. It is too general - the NewsController wants to map something like News to NewsViewModel but IMapper just says "maps something to something."

Instead, have a look at creating a generic variant such as IMapper<TFrom,TTo>. Then, you can set up container so that the NewsController receives an IMapper<News,NewsModel> which is unambiguous and should uniquely match the NewsMapper component (however you decide to set that up.)

Edit

For examples/variants on the generic mapper theme see:

  • http://consultingblogs.emc.com/owainwragg/archive/2010/12/15/automapper-profiles.aspx
  • http://lucisferre.net/2009/12/31/graphite-update-the-automapfilter-for-model-e280933e-viewmodel-mapping/
  • Specifying a default Unity type mapping for a generic interface and class pair
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜