Всем привет! Я часто ищу в просторах интернета «идеальную архитектуру» и несколько месяцев назад наткнулся на интересную реализацию и хотел бы поделится немного дополнив его.
> Ссылка на реализацию
Немного модернизации и я получил вполне универсальный рабочий шаблон.
Для всех, кто не знаком с DDD можно начать с wiki.
В конце мы получим связку с DDD + CQRS + Entity Framework + OData + WebApi + Log4Net + Castle Windsor + Kendo UI.
Звучит громоздко, но сугубо лично, в результате получаем вполне легко масштабируемую систему.
namespace Web.Application
{
using System.Linq;
using System.Web.Http.OData;
using Infrastructure.Domain;
using Infrastructure.EntityFramework;
public class ReadODataControllerBase<TEntity> : ODataController
where TEntity : class, IEntity
{
private readonly IRepository<TEntity> _repository;
public ReadODataControllerBase(IRepository<TEntity> repository)
{
_repository = repository;
}
public IQueryable<TEntity> Get()
{
return _repository.Query();
}
}
}
namespace Web.Application
{
using System;
using System.Net;
using System.Web.Mvc;
using Castle.Core.Logging;
using Castle.Windsor;
using Infrastrcuture.Web.Forms;
using Infrastructure.Domain.Exceptions;
using Infrastructure.EntityFramework;
using Services.Account;
using Services.Account.Models;
public class FormControllerBase : Controller, ICurrentUserAccessor
{
public JsonResult Form<TForm>(TForm form)
where TForm : IForm
{
var formHanlderFactory = ResolveFormHandlerFactory();
var unitOfWork = ResolveUnitOfWork();
var logger = ResolveLogger();
try
{
logger.Info($"Begin request of <{CurrentUser.DisplayNameWithNk}> with form <{ form.GetType().Name }>.");
formHanlderFactory.Create<TForm>().Execute(form);
unitOfWork.SaveChanges();
logger.Info($"Complete request of <{CurrentUser.DisplayNameWithNk}> with form <{ form.GetType().Name }>.");
return Json(new { form });
}
catch (BusinessException be)
{
return JsonError(form, be, logger);
}
catch (FormHandlerException fhe)
{
return JsonError(form, fhe, logger);
}
catch (Exception e)
{
return JsonError(form, e, logger);
}
}
//Add exception logging
public FileResult FileForm<TForm>(TForm form)
where TForm : IFileForm
{
var formHanlderFactory = ResolveFormHandlerFactory();
formHanlderFactory.Create<TForm>().Execute(form);
return File(form.FileContent, System.Net.Mime.MediaTypeNames.Application.Octet, form.FileName);
}
private JsonResult JsonError<TForm>(TForm form, Exception e, ILogger logger)
{
logger.Error($"Rollback request of <{CurrentUser.DisplayNameWithNk}> with form <{ form.GetType().Name }>.", e);
Response.TrySkipIisCustomErrors = true;
Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return Json(new
{
form,
exceptionMessage = e.Message
});
}
#region Dependency resolution
private IFormHandlerFactory ResolveFormHandlerFactory()
{
return GetContainer().Resolve<IFormHandlerFactory>();
}
private IUnitOfWork ResolveUnitOfWork()
{
return GetContainer().Resolve<IUnitOfWork>();
}
private ILogger ResolveLogger()
{
return GetContainer().Resolve<ILogger>();
}
private IWindsorContainer GetContainer()
{
var containerAccessor = HttpContext.ApplicationInstance as IContainerAccessor;
return containerAccessor.Container;
}
private ICurrentUserKeeper ResolveCurrentUserKeeper()
{
return GetContainer().Resolve<ICurrentUserKeeper>();
}
#endregion
#region CurrentUserAccessor Memebers
public ApplicationUser CurrentUser
{
get
{
var currentUserKeeper = ResolveCurrentUserKeeper();
return currentUserKeeper.GetCurrentUser();
}
}
#endregion
}
}
namespace Web.Application.Station
{
using Domain.Model.Station;
using Infrastructure.EntityFramework;
public class StationsController : ReadODataControllerBase<Station>
{
public StationsController(IRepository<Station> repository) : base(repository)
{
}
}
}
namespace Web
{
using System.Linq;
using System.Web.Http;
using System.Web.Http.OData.Builder;
using System.Web.Http.OData.Extensions;
using Domain.Model.Station;
using Infrastrcuture.Web.Extensions;
using Microsoft.Data.Edm;
public class ODataConfig
{
public static void Register(HttpConfiguration config)
{
var builder = new ODataConventionModelBuilder();
config.Routes.MapODataServiceRoute("odata", "odata", GetEdmModel(builder));
}
public static IEdmModel GetEdmModel(ODataConventionModelBuilder builder)
{
var entityTypes = typeof (Station).Assembly.GetTypes().Where(x => x.IsClass && !x.IsNested);
var method = builder.GetType().GetMethod("EntitySet");
foreach (var entityType in entityTypes)
{
var genericMethod = method.MakeGenericMethod(entityType);
genericMethod.Invoke(builder, new object[]
{
entityType.Name.Pluralize()
});
}
return builder.GetEdmModel();
}
}
}
К сожалению, не доступен сервер mySQL