используя mef с asp.net mvc 3 - PullRequest
       35

используя mef с asp.net mvc 3

1 голос
/ 22 декабря 2011

Я пытаюсь использовать MEF в своем приложении asp.net mvc 3, но я не смог реализовать инъекцию. Вот код:

У меня есть библиотека классов интерфейсов, которая имеет:

namespace Namespace.Interfaces
{
    public interface IMessenger
    {
        string GetMessage();
    }
}

И в другой библиотеке классов у меня есть наследование класса от IMessenger:

namespace Namespace.Message
{
    [Export(typeof(IMessenger))]
    public class Messenger : IMessenger
    {
        public Messenger()
        {

        }

        public string GetMessage() 
        {
            return "Mef Test!";
        }
    }
}

В моем приложении есть каталог "Parts", и я копирую dll библиотеки классов, которая содержит класс с именем "Messenger".

В global.asax у меня есть:

    private static CompositionContainer _container;

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        DirectoryCatalog catalog = new DirectoryCatalog(Server.MapPath("Plugins"), "*.dll");
        _container = new CompositionContainer(catalog);
        _container.ComposeParts();

        DependencyResolver.SetResolver(new MefDependencySolver(_container));
    }

Вот класс MefDependencyResolver:

public class MefDependencySolver : IDependencyResolver
{
    public MefDependencySolver(CompositionContainer compositionContainer)
    {
        this.compositionContainer = compositionContainer;
    }

    private CompositionContainer compositionContainer;

    public object GetService(Type serviceType)
    {
        string name = AttributedModelServices.GetContractName(serviceType);

        return compositionContainer.GetExportedValueOrDefault<object>(name);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return this.compositionContainer.GetExportedValues<object>(serviceType.FullName);
    }
}

И, наконец, я пытаюсь использовать его в своем контроллере так:

public class HomeController : Controller
{
    [ImportAttribute]
    public IMessenger _messenger { get; set; }

    public HomeController()
    {

    }

    public ActionResult Index()
    {
        ViewBag.Message = _messenger.GetMessage();

        return View();
    }
}

Но он не создает объект _messenger. Я получаю ссылку на объект, не установленную для экземпляра объекта. Что я делаю неправильно?

Заранее спасибо,

1 Ответ

1 голос
/ 22 декабря 2011

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

public IEnumerable<object> GetServices(Type type) 
    { 
        string name = AttributedModelServices.GetContractName(type); 

        try 
        { 
            return container.GetExportedValues<object>(name); 
        } 
        catch 
        { 
            return new object[] {}; 
        } 
    } 

Важно вернуть пустой список, если служба не может быть разрешена.заключается в том, чтобы способствовать внедрению конструктор, а не свойство.Требуется зависимость IMessenger, поэтому лучше запросить ее у конструктора.Вы можете переписать это так:

public HomeController : Controller
{
   private readonly IMessenger _messenger;

   [ImportingConstructor]
   public HomeController(IMessenger messenger)
   {
      _messenger = messenger;
   }

   // other actions
}

Я думаю, что проблема в этой строке _container.ComposeParts();.Я не думаю, что вы должны это называть.MEF сделает это за вас.

...