2015-07-16 20 views
6

Pracuję nad aplikacją C# MVC, używając wzorca repozytorium. Używam Unity jako mojego IoC w celu implementacji mojego repozytorium w aplikacji MVC.C# typy ogólne i wzór repozytorium

Utworzono następujący typ ogólny, którego celem jest ograniczenie do minimum replikacji kodu w aplikacjach. Oto przykład:

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; 
     } 

To działa doskonale podczas korzystania strategię TPC lub TPH, jednak to nie dobrze grać ze strategią TPT. Przykład:

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

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

Moja implementacja w 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; 
     } 
    } 

Pierwsza linia tego bloku kodu jest to, co mam problemy z. Aby zainicjować typ GenericRepository muszę wstawić klasę dla T. W tym przypadku DbContext C zawsze będzie taki sam, więc nie jest to problemem.

Jak mogę wdrożyć w pełni ogólny wzorzec, który będzie działać z odziedziczonymi typami? Gdyby to była niewielka liczba przedmiotów, nie martwiłbym się tym, ale nie jest tak w tej sytuacji. Myślę, że jest na pewno lepszy sposób, aby sobie z tym poradzić, więc docieram do was wszystkich za wasz wkład.

+0

Jaki jest związek pomiędzy parametrem 'T' w sprawie Klasa GenericRepository i parametr 'T' na AddObjectAsync? – StriplingWarrior

+1

Czy byłaby to sytuacja, w której można użyć kompozycji do dziedziczenia? Jeśli ComponentRepository wstrzyknęło wyspecjalizowaną fabrykę zdolną do konstruowania instancji GenericRepository, wówczas 'AddComponentAsync' może wywołać tę fabrykę, aby skonstruować repozytorium generowane w sposób mocno generyczny na podstawie typu podanego w tej metodzie. – StriplingWarrior

+0

Przepraszamy, błędnie przeczytałem Twój komentarz. Oni są tacy sami. Jeśli przekażemy składnik "komponent", AddObjectAsync będzie typu i oczekuje parametru metody (encja składnika). –

Odpowiedz

0

Wygląda na to, że możesz mieć "nadmiarowy".

Generic DbContext wydaje się stratą czasu, jeśli jest mocno zakodowany w 2 miejscach. tj. GenericRepository<Component, HappyDbContext> i where C : DbContext, new(). Silne wpisanie pola _context i wstrzyknięcie HappyDbContext przy użyciu Unity z silnego repo typu maszynowego może mieć więcej sensu.

porusza także ogólny podmiot wpisać w dół do poziomu metody niż klasa może uprościć, a także:

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; 
     } 
    } 
} 

Mam nadzieję, że to pomaga