Как настроить хранилище в памяти - PullRequest
5 голосов
/ 31 марта 2011

У меня есть следующий класс:

public class InMemoryRepository : IRepository
{
    public void Add(object entity)
    {
        throw new NotImplementedException();
    }

    public void Attach(object Entity)
    {
        throw new NotImplementedException();
    }

    public T Get<T>(object id)
    {
        throw new NotImplementedException();
    }

    public IList<T> GetAll<T>(string queryName)
    {
        throw new NotImplementedException();
    }

    public IList<T> GetAll<T>()
    {
        throw new NotImplementedException();
    }

    public IQueryable<T> Query<T>()
    {
        throw new NotImplementedException();
    }

    public void Remove(object entity)
    {
        throw new NotImplementedException();
    }

    public void Save(object entity)
    {
        throw new NotImplementedException();
    }
}

Наша реализация репозитория по умолчанию использует NHibernate для резервного хранилища, но я хотел бы реализовать его версию в памяти, чтобы я мог создавать прототипы объектов доменабез необходимости создавать резервную базу данных SQL.Предполагая, что все объекты имеют свойство Id в качестве первичного ключа, как бы вы реализовали общее хранилище памяти для этого?

Некоторые ключевые моменты, с которыми мне трудно обращаться:

  • Сами методы репозитория являются общими, поэтому мне нужен механизм для автоматического хранения и ссылки на различные типы.Get<TestEntity>(object id) должен иметь возможность запрашивать все сохраненные экземпляры TestEntity и находить экземпляр с соответствующим свойством Id, но я не могу определить коллекцию объектов TestEntity напрямую, так как хранилище не будет знать, какие типы я передаю.до времени выполнения.
  • Мне нужно поддерживать LINQ to Objects для метода Query ().Предполагая, что я могу придумать достойный способ хранения объектов, это должно быть так же просто, как возвращать массив хранимых объектов AsQueryable ().

Как бы вы хранили объекты для удовлетворения вышеуказанных требований

Ответы [ 4 ]

5 голосов
/ 31 марта 2011

Основы просты:

public class InMemoryRepository : IRepository
{
    private readonly IList<object> entities = new List<object>();

    public T Get<T>(object id)
    {
        return entities.OfType<T>.SingleOrDefault(e => e.ID == id);
    }

    public IList<T> GetAll<T>()
    {
        return entities.OfType<T>.ToList();
    }

    public IQueryable<T> Query<T>()
    {
        return GetAll<T>.AsQueryable();
    }
}

Однако, как только дело доходит до public IList<T> GetAll<T>(string queryName), все усложняется.

Потенциально вы можете прибегнуть к реализации репозитория на основе SQLite для своих тестов.

2 голосов
/ 18 мая 2016

С ответом Антона я смог исправить свой собственный InMemoryRepository. Я изменил его, чтобы соответствовать классу в вопросе:

private readonly ConcurrentDictionary<Type, List<object>> ObjectList = new ConcurrentDictionary<Type, List<object>>();

public int Add<T>(T obj) where T : IIdentifier
{
    // instantiate if list does not exist for this object type
    if (!ObjectList.ContainsKey(typeof (T)))
        ObjectList[typeof(T)] = new List<object>();

    // get id
    var id = GetId<T>() + 1;

    // add object to list
    obj.Id = id;
    ObjectList[typeof(T)].Add(obj);

    return id;
}

public void Attach<T>(T obj) {
    // do not need to do anything
}

public T Get<T>(int id) where T : class, IIdentifier
{
    // check list exist
    if (!ObjectList.ContainsKey(typeof (T)))
        return null;

    return ObjectList[typeof(T)].OfType<T>().FirstOrDefault(n => n.Id == id);
}

public List<T> GetAll<T>(Func<T, bool> predicate) where T : new()
{
    // check list exist
    if (!ObjectList.ContainsKey(typeof(T)))
        return null;

    return ObjectList[typeof(T)].OfType<T>().Where(predicate).ToList();
}

public List<T> GetAll<T>()
{
    return ObjectList[typeof(T)].OfType<T>.ToList();
}

public IQueryable<T> Query<T>()
{
    return GetAll<T>.AsQueryable();
}

public int Remove<T>(int id) where T : IIdentifier
{
    // check list exist
    if (!ObjectList.ContainsKey(typeof(T)))
        return 0;

    // find object with matching id
    for (var i = 0; i < ObjectList[typeof(T)].Count; i++)
        if (ObjectList[typeof(T)].OfType<T>().ToList()[i].Id == id)
        {
            ObjectList[typeof(T)].RemoveAt(i);
            return id;
        }

    // object not found
    return 0;
}

public int Save<T>(T obj) where T : IIdentifier
{
    // check list exist
    if (!ObjectList.ContainsKey(typeof(T)))
        return 0;

    // find object with matching id
    for (var i = 0; i < ObjectList[typeof(T)].Count; i++)
        if (ObjectList[typeof(T)].OfType<T>().ToList()[i].Id == obj.Id)
        {
            ObjectList[typeof (T)][i] = obj;
            return obj.Id;
        }

    // object not found
    return 0;
}

#region Helper methods

private int GetId<T>() where T : IIdentifier
{
    return ObjectList[typeof(T)].Count == 0 ? 0 : ObjectList[typeof(T)].OfType<T>().Last().Id;
}

#endregion
2 голосов
/ 31 марта 2011

Я бы пошел с NHibernate, настроенным для базы данных SqlLite в памяти . Вы можете проверить свой реальный код и убедиться, что все работает правильно. Написание макета для репозитория может быть трудным, и если вы измените интерфейс IRepository, вам придется переопределить InMemoryRepository.

Для меня одним из больших преимуществ наличия NHibernate является возможность использования в базе данных памяти для тестирования.

1 голос
/ 25 августа 2013

Вот реализация поддельного репозитория на основе DbSet, включая поиск по первичным ключам:

http://refactorthis.wordpress.com/2011/11/30/generic-repository-fake-idbset-implementation-update-find-method-identity-key/

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