Создание приложения MVC ASP.NET с n-уровневой слабой связью с использованием MEF - PullRequest
3 голосов
/ 25 мая 2011

У меня есть проект MVC. модель, контроллер и вид имеют собственный проект, следовательно, 3 библиотеки. У меня также есть интерфейсы IFACADE, IBUSINESS & IDATALAYER (dll) с конкретной реализацией в DLL-библиотеках FACADE, BUSINESS & DATACCESS. Как я могу соединить их все вместе, используя MEF?

1 Ответ

0 голосов
/ 26 мая 2011

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

Это проектное решение, которое вы должны принять перед началом разработки. Возможно, вы сможете изменить это позже, но это потребует больше времени, и вам придется сделать много изменений. После того, как вы определите это, все станет намного проще.

Попробуйте определить контракты (интерфейсы), потому что контракт в MEF заменяет тесную связь типичного приложения. MEF использует контракт для сопоставления компонентов импорта и экспорта во время выполнения.

Если у вас есть хранилище для экс. ProductRepository, который имеет несколько методов, затем создайте интерфейс IProductRepository, который содержит эти методы, затем пометьте ProductRepository атрибутом экспорта следующим образом:

public interface IProductRepository
{
    IEnumerable<Product> GetProducts(Expression<Func<Product, bool>> query);
}

[Export(typeof(IProductRepository))]
public class ProductRepository : IProductRepository
{
    public IEnumerable<Product> GetProducts(Expression<Func<Product, bool>> query)
    {
        throw new NotImplementedException();
    }
}

Ради аргумента скажем, что у вас есть сервис для таких продуктов:

public interface IProductService
{
    IEnumerable<Product> GetLatestProducts(int items);
}

[Export(typeof(IProductService))]
public class ProductService : IProductService
{
    private IProductRepository _repository;


    [ImportingConstructor]
    public ProductService(IProductRepository repository)
    {
        this._repository = repository;
    }

    public IEnumerable<Product> GetLatestProducts(int items)
    {
        return _repository.GetProducts(p => p.DateCreated == DateTime.Today).OrderByDescending(p => p.DateCreated).Take(items);
    }
}

Помечая ваш репозиторий атрибутом Export, вы позволяете вашим службам импортировать тот же репозиторий через MEF. Как вы можете видеть, мы делегируем работу MEF CompositionContainer для предоставления ProductService экземпляра ProductRepository ... мы внедряем этот экземпляр, используя Dependency Injection через внедрение конструктора.

Тогда на ваших контроллерах MVC вы применяете тот же принцип, но теперь вы импортируете ProductService, а не ProductRepository ... что-то вроде этого:

[Export(typeof(IController))]
[ExportMetadata("Name","Product")]
public class ProductController : Controller
{
    private IProductService _service;

    [ImportingConstructor]
    public ProductController(IProductService service)
    {
        _service = service;
    }

    public ActionResult LatestProducts()
    {
        var model = _service.GetLatestProducts(3);
        return View(model);
    }
}

Экспортируя свои контроллеры, вы можете размещать свои контроллеры в любое время, в той же сборке или в отдельной сборке. Как вы можете видеть, я добавил еще один атрибут в контроллер, [ExportMetadata («Имя», «Продукт»)]. Это используется, чтобы решить, какой контроллер выбрать из контейнера композиции при запросе.

Теперь вам нужно создать контейнер компоновщика совпадений => из некоторого каталога: TypeCalog, DirectoryCatalog, AssemblyCatalog или AggregateCatalog. Вы говорите каталогу, где загружать сборки. Вы можете прочитать больше в codeplex

Теперь вам нужен способ как-то получить ваши контроллеры из CompositionContainer. Место, где вы можете сделать это в MVC - ControllerFactory. Вы должны создать пользовательский ControllerFactory (наследуя DefaultControllerFactory или реализуя интерфейс IControllerFactory). Затем внутри фабрики контроллеров вы запрашиваете составной контейнер и находите запрошенный контроллер.

Как вы, вероятно, понимаете, процесс компоновки начинается с фабрики контроллеров: ProductController импортирует ProductService, а ProductService импортирует ProductRepository. Составной контейнер MEF просматривает граф зависимостей и удовлетворяет этим импортам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...