Шаблон хранилища EntityFramework - как написать лямбда-код GetByID внутри класса шаблона? - PullRequest
3 голосов
/ 31 мая 2010

Я пытаюсь написать универсальный класс шаблонов шаблонов репозитория «один размер подходит для большинства» для проекта на основе Entity Framework, над которым я сейчас работаю. Интерфейс (сильно упрощенный):

internal interface IRepository<T> where T : class
{
  T GetByID(int id);
  IEnumerable<T> GetAll();
  IEnumerable<T> Query(Func<T, bool> filter);
}

GetByID оказывается убийцей. В реализации:

public class Repository<T> : IRepository<T>,IUnitOfWork<T> where T : class
{
  // etc...
  public T GetByID(int id)
  {
    return this.ObjectSet.Single<T>(t=>t.ID == id);
  }

t => t.ID == id - это конкретный бит, с которым я борюсь. Можно ли даже написать лямбда-функции, подобные этой, в шаблонных классах, где информация о классе не будет доступна?

Ответы [ 2 ]

4 голосов
/ 02 августа 2010

Я определил интерфейс:

public interface IIdEntity
{
    long Id { get; set; }
}


И изменил шаблон t4, который генерирует мои классы POCO, так что каждый класс должен реализовывать открытый интерфейс IIdEntity interface.

Как это:

using System.Diagnostics.CodeAnalysis;
public partial class User : IIdEntity
{
    public virtual long Id
    {
        get;
        set;
    }

С помощью этой модификации я могу написать общий GetById (длинный идентификатор), например:

public T GetById(long id)
{
    return Single(e => e.Id == id);
}

IRepository определяется следующим образом:

/// <summary>
/// Abstract Base class which implements IDataRepository interface.
/// </summary>
/// <typeparam name="T">A POCO entity</typeparam>
public abstract class DataRepository<T> : IDataRepository<T>
    where T : class, IIdEntity
{
2 голосов
/ 31 мая 2010

Вы можете просто создать небольшой интерфейс, содержащий Id-свойство, и ограничить T типами, которые его реализуют.

EDIT: На основании комментария, если вы согласитесь с тем фактом, что компилятор не поможет вам убедиться, что свойство Id действительно существует, вы можете сделать что-то вроде этого:

public class Repo<T> where T : class
{
    private IEnumerable<T> All()
    {
        throw new NotImplementedException();
    }

    private bool FilterOnId(dynamic input, int id)
    {
        return input.Id == id;
    }

    public T GetById(int id)
    {
        return this.All().Single(t => FilterOnId(t, id));
    }
}
...