MVC3 Generic CRUD Контроллеры, Сервисы и Репозитории - PullRequest
4 голосов
/ 11 января 2012

Мы пытаемся создать универсальный контроллер CRUD в нашем приложении MVC3, который может выполнять следующие действия: Редактировать (Создать / Редактировать), Удалить и Список (я уже посмотрел здесь ). Проект имеет веб-слой (MVC), сервисный (BLL) слой и слой репозитория (DB). Мы используем конструирование зависимости следующим образом:

SERVICE LAYER
public class MyService : IMyService
{
    private IMyRepository _myRepository;

    public MySerivce(IMyRepository myRepository)
    {
        this._myRepository = myRepository;
    }

    public IEnumerable<IMyObject> GetObjects(int intParentKey)
    {
        return (IMyObject)_myRepository.GetObjects(intParentKey).Select(o => new MyObject(o));;
    }
}


CONTROLLER
public class MyController
{
    private IMyService _myService;

    public MyController(IMyService myService)
    {
        this._myService = myService;
    }

    public ActionResult Index()
    {
        return View("Index", new List<MyFormModel>(_myService.GetObjects(intKeyValue).Select(a => new MyFormModel(a))));
    }
}

Цель состоит в том, чтобы иметь общий контроллер CRUD, но сложность заключается в том, что контроллеры должны знать объект MyFormModel, а также конкретную службу. Мы также хотели бы иметь универсальный сервис, который обрабатывает функции GetObjects, SaveObject, DeleteObject, но тогда для этого потребуются знания интерфейса IMyObject, реализации IMyObject Myybject и типа IMyRepository. Сейчас кажется, что делать все это с помощью внедрения зависимостей несколько сложно.

К вашему сведению, уровень сервиса должен изменяться на лету в пределах WEB-части инструмента в зависимости от текущей конфигурации.

В ответ на общий комментарий CRUD, вот контроллер BASE, который принимает службу BASE посредством внедрения зависимости:

public abstract class BaseCRUDController<T>
    where T : class
{
    private IBaseService _baseService;

    public BaseCRUDController(IBaseService baseService)
    {
        this._baseService = baseService;
    }

    public ActionResult Index()
    {
        Type classType = typeof(T);
        ConstructorInfo ciClass = classType.GetConstructor(new Type[] {});
        return View("Index", new List<T>(_baseService.GetObjects(intKey).Select(o => (T)ciClass.Invoke(new object[] { o }))));
    }
}

Очевидно, что этот универсальный контроллер довольно прост, но трудность связана со стороной обслуживания, где находятся объекты IMyObject и MyObject. Определение универсального BaseService потребует от вас включения типов всех объектов в базовый контроллер, чего мы и пытаемся избежать. Код, приведенный ниже, может быть не совсем понятен, поэтому я прошу помощи:

SERVICE CLASS
public class MySerivce : BaseService<IMyObject, MyObject, DBObject>
{
    public MySerivce(IMyRepository myRepository) :
        base(myRepository)
    {
    }
}

BASE SERVICE INTERFACE
public interface IBaseService<IMT, MT, DT>
    where IMT : class
    where MT : class
    where DT : class
{
    IEnumerable<ValidationResult> Save(IMT model);
    void Delete(int intKey);
    IMT Get(int? intKey);
    IEnumerable<IMT> GetObjects(int intParentKey);
}


BASE SERVICE IMPLEMENTATION
public class BaseService<IMT, MT, DT> : IBaseService<IMT, MT, DT>
where IMT : class
where MT : class
where DT : class
{
private IBaseRepository _baseRepository;

public BaseService(IBaseRepository baseRepository)
{
    this._baseRepository = baseRepository;
}

public IEnumerable<ValidationResult> Save(IMT model)
{
    List<ValidationResult> lResults = new List<ValidationResult>();

    if (Validator.TryValidateObject(model, new ValidationContext(model, serviceProvider: null, items: null), lResults))
    {
        Type tDT = typeof(DT);
        ConstructorInfo ciDTClass = tDT.GetConstructor(new Type[] { });
        DT dtObject = (DT)ciDTClass.Invoke(new object[] { });
        Mapper.CreateMap<IMT, DT>();
        Mapper.Map(model, dtObject);

        _baseRepository.Save<DT>(dtObject);
    }

    return lResults;
}

public void Delete(int intKey)
{
    _baseRepository.Delete<DT>(intKey);
}

public IMT Get(int? intKey)
{
    Type tMT = typeof(MT);
    ConstructorInfo ciMTClass = tMT.GetConstructor(new Type[] { });
    DT dtObject = _baseRepository.Get<DT>(intKey);

    if (dtObject == null)
    {
        Type tDT = typeof(DT);
        ConstructorInfo ciDTClass = tDT.GetConstructor(new Type[] { });
        dtObject = (DT)ciDTClass.Invoke(new object[] { });
    }

    return (IMT)ciMTClass.Invoke(new object[] { dtObject });
}

public IEnumerable<IMT> GetObjects(int intParentKey)
{
    Type tMT = typeof(MT);
    ConstructorInfo ciMTClass = tMT.GetConstructor(new Type[] { });
    IEnumerable<DT> dbObjects = _baseRepository.GetObjects<DT>(intParentKey);

    return (IEnumerable<IMT>)dbObjects.Select(o => (MT)ciMTClass.Invoke(new object[] { o })); ;
}
}
...