Создание общего метода Save () для моделей - PullRequest
3 голосов
/ 18 июня 2011

У меня довольно простая система, и для целей этого вопроса, по сути, есть три части: Модели, Репозитории, Код приложения.

В основе лежат модели.Давайте использовать простой надуманный пример:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

В этом же проекте используется универсальный интерфейс хранилища.Самое простое:

public interface IRepository<T>
{
    T Save(T model);
}

Реализации этого интерфейса находятся в отдельном проекте и внедрены в StructureMap.Для простоты:

public class PersonRepository : IRepository<Person>
{
    public Person Save(Person model)
    {
        throw new NotImplementedException("I got to the save method!");
        // In the repository methods I would interact with the database, or
        // potentially with some other service for data persistence.  For
        // now I'm just using LINQ to SQL to a single database, but in the
        // future there will be more databases, external services, etc. all
        // abstracted behind here.
    }
}

Итак, в коде приложения, если бы я хотел сохранить модель, я сделал бы это:

var rep = IoCFactory.Current.Container.GetInstance<IRepository<Person>>();
myPerson = rep.Save(myPerson);

Достаточно просто, но кажется, что это можно автоматизироватьмного.Этот шаблон сохраняется во всем коде приложения, поэтому я хочу создать единый универсальный Save() для всех моделей, который будет просто кратким вызовом приведенного выше кода приложения.Таким образом, нужно будет только позвонить:

myPerson.Save();

Но я не могу найти способ сделать это.Может быть, это обманчиво просто, и я просто не смотрю на это с правильной точки зрения.Сначала я попытался создать пустой интерфейс ISaveableModel<T> и намеревался сделать так, чтобы каждая «способная к сохранению» модель реализовывала его, затем для одного общего метода Save() у меня было бы расширение интерфейса:

public static void Save<T>(this ISaveableModel<T> model)
{
    var rep = IoCFactory.Current.Container.GetInstance<IRepository<T>>();
    model = rep.Save(model);
}

Но он говорит мне, что rep.Save(model) имеет недопустимые аргументы.Кажется, что это не связывает вывод типа, как я надеялся.Я попробовал аналогичный подход с классом BaseModel<T>, от которого наследуются модели:

public class BaseModel<T>
{
    public void Save()
    {
        this = IoCFactory.Current.Container.GetInstance<IRepository<T>>().Save(this);
    }
}

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

Ответы [ 2 ]

3 голосов
/ 18 июня 2011

Решит ли это общий метод расширения?

public static T Save<T>(this T current)
{
    var rep = IoCFactory.Current.Container.GetInstance<IRepository<T>>();
    rep.Save(current);
}

Затем вы можете ограничить его вашим ISaveableModel<T> интерфейсом.Приведенный выше тип возврата не реализован, но вы можете поместить его в логическое значение или флаг состояния, что угодно.

1 голос
/ 18 июня 2011

В обоих подходах параметр функции Save() не относится к типу T. В первом это ISaveableModel<T>, а во втором BaseModel<T>. Поскольку хранилище является универсальным, основанным на T, метод Save будет ожидать переменную типа T. Вы можете добавить простое приведение к T, прежде чем вызывать Save, чтобы исправить это.

Кроме того, ваш IRepostory<T> может быть изменен на

public interface IRepository<T>
{
    T Save(ISaveableModel<T> model);
}

, что имеет больше смысла.

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