Zwiebel Architektur, die Einheit der Arbeit und ein generic Repository pattern

Dies ist das erste mal, dass ich bin Implementierung eines domain-driven-design-Ansatz. Ich habe beschlossen, zu versuchen die Zwiebel Architektur, wie es konzentriert sich auf die domain statt auf Infrastruktur/Plattformen/etc.

Zwiebel Architektur, die Einheit der Arbeit und ein generic Repository pattern

Um abstrakte Weg vom Entity Framework, habe ich eine generic repository mit einem Arbeitseinheit Umsetzung.

Den IRepository<T> und IUnitOfWork Schnittstellen:

public interface IRepository<T>
{
    void Add(T item);

    void Remove(T item);

    IQueryable<T> Query();
}

public interface IUnitOfWork : IDisposable
{
    void SaveChanges();
}

Entity Framework-Implementierungen von IRepository<T> und IUnitOfWork:

public class EntityFrameworkRepository<T> : IRepository<T> where T : class
{
    private readonly DbSet<T> dbSet;

    public EntityFrameworkRepository(IUnitOfWork unitOfWork)
    {
        var entityFrameworkUnitOfWork = unitOfWork as EntityFrameworkUnitOfWork;

        if (entityFrameworkUnitOfWork == null)
        {
            throw new ArgumentOutOfRangeException("Must be of type EntityFrameworkUnitOfWork");
        }

        dbSet = entityFrameworkUnitOfWork.GetDbSet<T>();
    }

    public void Add(T item)
    {
        dbSet.Add(item);
    }

    public void Remove(T item)
    {
        dbSet.Remove(item);
    }

    public IQueryable<T> Query()
    {
        return dbSet;
    }
}

public class EntityFrameworkUnitOfWork : IUnitOfWork
{
    private readonly DbContext context;

    public EntityFrameworkUnitOfWork()
    {
        this.context = new CustomerContext();;
    }

    internal DbSet<T> GetDbSet<T>()
        where T : class
    {
        return context.Set<T>();
    }

    public void SaveChanges()
    {
        context.SaveChanges();
    }

    public void Dispose()
    {
        context.Dispose();
    }
}

Den Kunden repository:

public interface ICustomerRepository : IRepository<Customer>
{

}

public class CustomerRepository : EntityFrameworkRepository<Customer>, ICustomerRepository 
{
    public CustomerRepository(IUnitOfWork unitOfWork): base(unitOfWork)
    {
    }
}

ASP.NET MVC-controller arbeiten mit dem repository:

public class CustomerController : Controller
{
    UnityContainer container = new UnityContainer();

    public ActionResult List()
    {
        var unitOfWork = container.Resolve<IUnitOfWork>();
        var customerRepository = container.Resolve<ICustomerRepository>();

        return View(customerRepository.Query());
    }

    [HttpPost]
    public ActionResult Create(Customer customer)
    {
        var unitOfWork = container.Resolve<IUnitOfWork>();
        var customerRepository = container.Resolve<ICustomerRepository>();; 

        customerRepository.Add(customer);

        unitOfWork.SaveChanges();

        return RedirectToAction("List");
    }
}

Dependency injection with unity:

container.RegisterType<IUnitOfWork, EntityFrameworkUnitOfWork>();
container.RegisterType<ICustomerRepository, CustomerRepository>();

Lösung:

Zwiebel Architektur, die Einheit der Arbeit und ein generic Repository pattern

PROBLEME?

  • Repository-Implementierung (EF-code) ist sehr allgemein gehalten. Alles sitzt in der Seite, die EntityFrameworkRepository<T> Klasse. Konkrete Modell-repositories nicht enthalten, diese Logik. Das spart mir aus schreiben von Tonnen redundanter code, sondern möglicherweise Opfer Flexibilität?

  • Den ICustomerRepository und CustomerRepository Klassen sind im Grunde leer. Sie sind rein da, um Abstraktion. Soweit ich das verstanden habe, passt sich dieser mit der vision, die Zwiebel Architektur, Infrastruktur-und Plattform-abhängigen code sitzt auf der Außenseite von Ihrem system, aber mit leere Klassen und leere Schnittstellen fühlt sich falsch an?

  • Verwenden eine unterschiedliche Persistenz-Implementierung (sagen, Azure Table Storage), dann eine neue CustomerRepository Klasse erstellt werden müssen, und die Erben würde eine AzureTableStorageRepository<T>. Aber dies könnte führen zu redundanter code (mehrere CustomerRepositories)? Wie würde dieser Effekt Spott?

  • Andere Implementierung (z.B. Azure Table Storage) hat Beschränkungen der transnationalen Unterstützung, damit die eine AzureTableStorageUnitOfWork Klasse würde nicht funktionieren, in diesem Zusammenhang.

Gibt es andere Probleme mit der Art, wie ich dies getan habe?

(Ich teilgenommen habe, die meisten meiner inspiration aus dieser Beitrag)

  • Sie sind über die service locator anti-pattern, indem Sie eine Abhängigkeit von der IoC-container. Stattdessen sollten Sie sich eine factory-Klasse zu injizieren in Ihre controller. Einige IoC-Container kann produzieren diese für Sie in form eines Func<T> Abhängigkeit
InformationsquelleAutor Dave New | 2013-12-09
Schreibe einen Kommentar