2015-07-16 16 views
6

Ich arbeite an einer C# MVC-Anwendung mit dem Repository-Muster. Ich verwende Unity als meinen IoC, um mein Repository in der MVC-Anwendung zu implementieren.C# generische Typen und Repository-Muster

Ich habe den folgenden generischen Typ erstellt mit dem Ziel, Code-Replikation in meinen Anwendungen zu minimieren. Hier ist ein Beispiel:

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

Das ist großartig zu arbeiten, wenn ich eine TPC oder TPH-Strategie verwenden, aber es nicht gut spielt mit einer TPT-Strategie. Ein Beispiel:

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

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

Meine Umsetzung im 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; 
     } 
    } 

Die erste Zeile dieses Codeblock ist das, was Ich habe Probleme mit. Um den Typ GenericRepository zu initialisieren, muss ich eine Klasse für T einfügen. In diesem Fall ist der DbContext C immer derselbe, so dass er nicht von Belang ist.

Wie kann ich ein vollständig generisches Muster implementieren, das mit geerbten Typen funktioniert? Wenn es eine kleine Anzahl von Gegenständen wäre, wäre ich weniger besorgt darüber, aber das ist in dieser Situation nicht der Fall. Ich denke, dass es sicherlich einen besseren Weg gibt, damit umzugehen, deshalb richte ich mich an euch alle für eure Beiträge.

+0

Was ist die Beziehung zwischen den 'T' Parametern auf dem GenericRepository-Klasse und der 'T'-Parameter auf AddObjectAsync? – StriplingWarrior

+1

Wäre dies eine Situation, in der Sie die Komposition über die Vererbung verwenden könnten? Wenn ComponentRepository eine spezialisierte Factory injiziert, die in der Lage ist, GenericRepository-Instanzen zu konstruieren, kann 'AddComponentAsync' diese Factory aufrufen, um basierend auf dem für diese Methode bereitgestellten Typ ein stark generisch typisiertes Repository zu erstellen. – StriplingWarrior

+0

Entschuldigung, ich habe Ihren Kommentar falsch gelesen. Sie sind gleich. Wenn wir die Entity "Component" übergeben, wird AddObjectAsync vom Typ sein und einen Methodenparameter von (Component entity) erwarten. –

Antwort

0

Es sieht so aus, als ob Sie einen Fall von "über-Generika" haben könnten.

Generieren der DbContext generische scheint eine Verschwendung von Zeit, wenn es an 2 Stellen fest codiert ist. d.h. GenericRepository<Component, HappyDbContext> und where C : DbContext, new(). Starke Eingabe des Feldes _context und injizieren HappyDbContext mit Unity von den starken typisierten Repos könnte mehr Sinn machen.

bewegen sich auch die allgemeine Entitätstyp eher auf die Methode Ebene tiefer als die Klasse der Dinge vereinfachen könnte genauso gut:

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

Hoffentlich hilft

Verwandte Themen