1

I'm currently working on a n-tier web application using ASP.NET Web API 2. It has been decided to use boilerplate as DI framework. Now, I need to reconsider the architecture that ties the business layer to the persistence layer. The current architecture is making use of a Persistence Facade that exposes the writing/reading database operations (Applying UML and Patterns by Craig Larman).

public class PersistenceFacade
{
    //AS SINGLETON

    private static PersistenceFacade _istance = null;

    protected PersistenceFacade()
    {
        mappers = new Dictionary<string, IRelationalDBMapper>();
        mappers.Add("AnnotatoDto", new AnnotatiRDBMapper());
        mappers.Add("AppuntatoRequestDto", new AppuntatiRDBMapper());
    }

    public static PersistenceFacade GetIstance()
    {
       ... return Singleton Istance...
    }

    //AS CLASS

    Dictionary<string, IRelationalDBMapper> mappers;

    public Object Get(OID oid, string persistenceClass)
    {
        IRelationalDBMapper mapper = (IRelationalDBMapper)mappers[persistenceClass];
        return mapper.Get(oid);
    }

    public bool Put(OID oid, Object obj)
    {... mapper.Put(oid, obj);}

    public bool Delete(OID oid, Object obj)
    {... mapper.Put(oid, obj);}

}

Now the Mapper Interface abstracts on how DTOs are mapped to db objects

public interface IRelationalDBMapper
{

    Object Get(OID oid);

    bool Put(OID oid, Object obj);

    bool Delete(OID oid, Object obj);
}

this interface is implemented by:

public class FooRDBMapper : IRelationalDBMapper
{
    IDocumentStoreService _dbConnector;

    public AppuntatiRDBMapper()
    {
        _dbConnector = IocManager.Instance.Resolve<IDocumentStoreService>();
    }

    public object Get(OID oid)
    {...}

    public bool Put(OID oid, object obj)
    {...
        _dbConnector.AddAppuntato(oid, appuntato)...
    }

    public bool Delete(OID oid, Object obj)
    {
        ..._dbConnector.DeleteAppuntato(userOid, appuntato);...
    }
}

and

BarRDBMapper : IRelationalDBMapper{
    ...similar to FooRDBMapper...
}

Finally, I Have an App Domain class:

public class UserNavigationService{

    ...

    AddFoo(UserOID oid, Foo foo){

        return PersistenceFacade.GetIstance().Put(oid, foo);
    }
    ...other methods like: DeleteFoo, AddBar, GetBar  ecc.....
}

What I want to achieve is to disassemble this Pattern, since I need to use DI to Inject to PersistenceFacade some dependencies (IConfigurationService, IPathTranslator ecc...). Using DI forces me to reconsider the whole thing. I want an architecture that in UserNavigationService allows me to write:

...
IPersistenceService<IDocumentService> _dbService;

public UserNavigationService(IPersistenceService<IDocumentService> dbService, ...){
    ...
}

AddFoo(UserOID oid, Foo foo){
    return _dbService.Put<FooDTO>(oid, foo);
}

In particular I need to make two abstractions: what kind of database (Oracle, MongoDB, XML files), and what kind of object (Foo, Bar). I can't really figure out how to do.

I have a IDocumentStoreService, which is an interface that exposes all the methods for storing/gathering all the data from all the various database. (I need this abstraction since I'm going to migrate to another relational database). An implementing class of this interface might be ThatDBDocumentService.

  • why does di force to you to reconsider? have you tried named dependencies? – Ewan Jan 31 '17 at 9:46
  • sorry, but I'm not sure on what do you mean by 'named depedecies' – davideAlbertini Jan 31 '17 at 9:50
  • ok, i will write an answer.. – Ewan Jan 31 '17 at 9:50
  • Reading the documentation for ASP.NET Boilerplate is depressing. They don't seem to know what inversion of control is but they refer to it immediately. Looks like a cruft factory. – Aluan Haddad Jul 31 '17 at 16:28
1

You can use your pattern with a DI container.

As I understand it the main problem is that you have more than one IRelationalDBMapper, for example, and need to inject the correct one into a UserNavigationService.

You can do this using Named Dependencies.

Essentially as well as resolving by type, you can also add a random 'name' to something that you register. This allows you to specify that other objects use a dependency which matches both type AND name when they are constructed

References:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.