2015-07-16 3 views
6

Я работаю над приложением C# MVC с использованием шаблона репозитория. Я использую Unity в качестве моего IoC для реализации моего репозитория в приложении MVC.C# общие типы и шаблон репозитория

Я создал следующий общий тип с целью сведения к минимуму репликации кода во всех приложениях. Вот пример:

public abstract class GenericRepository<T, C> : IDisposable,IGenericRepository<T> where T : class where C : DbContext, new() 


public async void AddObjectAsync<T>(T entity) where T : class 
    { 
     try 
     { 
      // Validate that that there is not an existing object in the database. 
      var x = _context.Entry(entity); 
      if (!Exists(entity)) 
      { 
       _context.Set<T>().Add(entity); // Add the entry if it does not exist. 
       _context.SaveChanges(); 
      } 
      else 
      { 
       UpdateObjectAsync(entity); // Update the entry if it did exist. 
      } 
     } 
     catch 
     { 
      throw; 
     } 

Это работает прекрасно, когда я использую УМП или Тф стратегию, однако это не хорошо играть со стратегией ТРТ. Пример:

public abstract class Component 
{ 
    [Key] 
    public Guid ComponentId { get; set; } 

    public string Manufacturer { get; set; } 
} 
public class SpecialComponent : Component 
{ 
    public string ExtraSpecialProperty { get; set; } 
} 

Моя реализация в ComponentRepository:

public class ComponentRepository : GenericRepository<Component, HappyDbContext>, IComponentRepository 
{ 
public async void AddComponentAsync<T>(T component) where T : class 
    { 
     try 
     { 

      if(component != null) 
      { 
       AddObjectAsync(component); 
      } 
      else 
      { 
      throw new ArgumentNullException(); 
      } 

     } 
     catch (ArgumentNullException ex) 
     { 
      _logger.WriteErrorLogAsync(ex); 
      throw ex; 
     } 
    } 

Первая строка этого блока кода то, что у меня возникают проблемы с. Чтобы инициализировать тип GenericRepository, мне нужно вставить класс для T. В этом случае DbContext C всегда будет таким же, поэтому он не вызывает беспокойства.

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

+0

Какова связь между 'параметром T' на Класс GenericRepository и параметр 'T' в AddObjectAsync? – StriplingWarrior

+1

Будет ли это ситуацией, когда вы можете использовать композицию над наследованием? Если ComponentRepository инжектировал специализированную фабрику, способную создавать экземпляры GenericRepository, то «AddComponentAsync» мог бы позвонить на этот завод, чтобы создать сильно типизированный типизированный репозиторий на основе типа, предоставленного этому методу. – StriplingWarrior

+0

Извините, я неправильно прочитал ваш комментарий. Они одинаковые. Если мы передадим объект «Компонент», то AddObjectAsync будет иметь тип и ожидать параметр метода (Компонентный объект). –

ответ

0

Похоже, что у вас может быть случай «чрезмерного».

Создание генератора DbContext кажется пустым, если оно жестко закодировано в 2-х местах. то есть GenericRepository<Component, HappyDbContext> и where C : DbContext, new(). Сильная набрав поле _context и вводя HappyDbContext с использованием Unity из сильного типированного репо, может иметь больше смысла.

перемещение также общий объект типа до уровня метода, а не класс может упростить вещи, а также:

public interface IGenericRepository 
{ 
    void AddObjectAsync<T>(T entity) where T : class; 
} 

public class GenericRepository : IGenericRepository 
{ 
    private readonly DbContext _context; 

    public GenericRepository(DbContext context) 
    { 
     _context = context; 
    } 

    .... 

    public async void AddObjectAsync<T>(T entity) where T : class 
    { 
     // Validate that that there is not an existing object in the database. 
     var x = _context.Entry(entity); 
     if (!Exists(entity)) 
     { 
      _context.Set<T>().Add(entity); // Add the entry if it does not exist. 
      _context.SaveChanges(); 
     } 
     else 
     { 
      UpdateObjectAsync(entity); // Update the entry if it did exist. 
     } 
    } 
} 

public interface IComponentRepository 
{ 
    void AddComponentAsync(Component component); 
    // or void AddComponentAsync<T>(T component); 
    // depends if you'll be reusing the ComponentRepository 
    // for types that inherit Component but still have individual tables... 
    // It was a little difficult to tell from your example. 
} 

public class ComponentRepository : GenericRepository, IComponentRepository 
{ 
    public ComponentRepository(DbContext context) : base(context) { } 

    ... 

    public async void AddComponentAsync(Component component) 
    { 
     try 
     { 
      if (component == null) throw new ArgumentNullException(); 
      AddObjectAsync(component); 
     } 
     catch (ArgumentNullException ex) 
     { 
      _logger.WriteErrorLogAsync(ex); 
      throw ex; 
     } 
    } 
} 

Надеется, что это помогает

Смежные вопросы