Этот конкретный пример показывает, как мы можем интегрировать MEF с новым DependencyResolver
MVC3, который обеспечивает механизм определения местоположения службы для различных точек расширения в архитектуре MVC.В моем блоге есть еще несколько статей, в которых подробно описывается, как может работать возможная архитектура плагинов. Они доступны по адресу:
- Модульный ASP.NET MVC с использованием инфраструктуры управляемых расширений (MEF), часть первая
- модульный ASP.NET MVC с использованием инфраструктуры управляемой расширяемости (MEF), часть вторая
- модульный ASP.NET MVCиспользование инфраструктуры управляемой расширяемости (MEF), часть третья
Есть также множество фантастических статей, мои рекомендации также будут читать:
ASP.NET MVC и платформа Managed Extensibility Framework (MEF) от Maarten Balliauw
Определение веб-областей с помощью MEF Тимом Робертсом
MVC - это очень гибкая архитектура, существует множество способов ее расширения, но из-за особенностей работы приложений ASP.NET в IIS необходимо очень тщательно рассмотреть время жизни детали.Например, контроллеры могут использоваться только для одного запроса, поэтому вам может потребоваться, чтобы ваши контроллеры имели определенный CreationPolicy
.Статья Тима Роберта, посвященная веб-деталям, особенно хороша для чтения.
Надеюсь, что этого достаточно, чтобы указать правильное направление.
Редактировать: из-за модульной природы, которую обеспечивает MEF,важно убедиться, что ваши разные слои отделены.Вы указали, что используете Entity Framework, но в действительности EF следует использовать только на уровне данных.Как правило, архитектура MVC будет продвигать модели представлений поверх моделей доменов.Для этого, вероятно, полезно использовать что-то похожее на шаблон репозитория, например, вот макет UserRepository
:
[Export(typeof(IUserRepository))]
public class UserRepository : IUserRepository
{
public IEnumerable<UserViewModel> GetUsers()
{
// Get values here from EF as domain models
// And return them as view models?
}
}
, который мы можем экспортировать и вставить в контроллер:
[ExportController("User"), PartCreationPolicy(CreationPolicy.NonShared)]
public class UserController : Controller
{
private readonly IUserRepository _repo;
[ImportingConstructor]
public UserController(IUserRepository repo)
{
if (repo == null)
throw new ArgumentNullException("repo");
_repo = repo;
}
public ActionResult Index()
{
var users = _repo.GetUsers();
return View(users);
}
}
Это просто очень простой пример, но, как и многие контейнеры IoC, MEF также поддерживает внедрение зависимостей.До тех пор, пока деталь обеспечивает подходящий экспорт, ее можно импортировать (либо с помощью внедрения свойства, либо с помощью конструктора) в другую деталь во время компоновки.
Я бы не рекомендовал использовать EF для ваших представлений, так какделает их явно зависимыми от него.Заботясь об отделении и представлении только нужных типов на нужных уровнях, ваша архитектура станет намного более надежной, гибкой и тестируемой, что сделает ее обслуживание и обновление намного проще.В качестве еще одного быстрого примера, вот как мы могли бы протестировать наш контроллер:
[Test]
public void UserController_CreatesViewResult_WithListOfUsers()
{
var mock = new Mock<IUserRepository>();
mock.Setup(m => m.GetUsers()).Returns(new[] { new UserViewModel { Name = "Matt" } });
var controller = new UserController(mock.Object);
var result = controller.Index();
Assert.That(result is ViewResult);
// Other assertions.
}
Поскольку я не тесно связал EF со своим видом, мой контроллер намного более тестируем, я могу смоделировать подходящий репозиторий ипроверить, где мне нужно.
Важным является планирование вашей архитектуры.