2016-04-03 5 views
1

Für jede Anfrage initialisieren, muss ich einige aktuelle Benutzerberechtigungen Daten aus der Datenbank erhalten und dann in der Logik diese Informationen mehrmals verwenden (die aus mehreren Objekten besteht)IoC - Objektzustand im Konstruktor

Ich möchte einmal pro Anfrage Daten aus der Datenbank abrufen und sie bei Bedarf wiederverwenden.

Ist das Folgende der beste Weg, dies zu tun?

1) definieren ein Objekt wie folgt

class ApplicationUser : IApplicationUserProvider 
{ 
    private UserPermissions _userPermissions; 
    ... 

    public ApplicationUser(IDatabase userService) 
    { 
     _userPermissions = userService.GetUserPermission(); // this would executed for every request once 
    } 

    UserRoles GetRoles() 
    { 
     return _userPermissions; 
    } 
} 

2) definieren, das IOC etwas wie diese

var container1 = new Container(c => 
      { 
     c.For<IDatabase>().Use<Database>(); 
     c.For<IApplicationUser>().Use<ApplicationUser >(); 
     c.For<IApplicationLogic1>().Use<ApplicationLogic1>(); // this has IApplicationUser in ctor 
     c.For<IApplicationLogic2>().Use<ApplicationLogic2>(); // this has IApplicationUser in ctor 
      }); 

3) die Steuerung

void PageController(IApplicationLogic1 l1) 
{ 
    l1.Process(); 
    l2.Process(); 
} 

Antwort

1

Die UserPermissions Informationen wäre, ist Laufzeitdaten, und wie erklärt here, sollten Laufzeitdaten nicht während der Konstruktion der Objektgraphen injiziert oder aufgelöst werden.

Stattdessen sollte der Aufruf an userService.GetUserPermission() aus dem Konstruktor verschoben werden. Zum Beispiel durch den Anruf zu verzögern, indem ein Lazy<T>:

class ApplicationUser : IApplicationUserProvider 
{ 
    private Lazy<UserPermissions> _userPermissions; 

    public ApplicationUser(IDatabase userService) { 
     _userPermissions = new Lazy<UserPermissions>(userService.GetUserPermission); 
    } 

    UserRoles GetRoles() { 
     return _userPermissions.Value.GetRoles(); 
    } 
} 

Eine weitere Option ist es, ein Dekorateur auf IDatabase zu definieren, die das Caching implementieren: innerhalb der PerRequestCacheDatabaseDecorator

public class PerRequestCacheDatabaseDecorator : IDatabase 
{ 
    private IDatabase _decoratee; 

    public PerRequestCacheDatabaseDecorator(IDatabase decoratee) { 
     _decoratee = decoratee; 
    } 

    public UserPermissions GetUserPermission() { 
     var items = HttpContext.Current.Items; 
     if (items["permissions"] == null) 
      items["permissions"] = _decoratee.GetUserPermission(); 
     return (UserPermissions)items["permissions"]; 
    } 
} 

Durch die reale Datenbank Umwickeln Sie können vereinfachen die ApplicationUser auf die folgenden:

class ApplicationUser : IApplicationUserProvider 
{ 
    private IDatabase _userService; 

    public ApplicationUser(IDatabase userService) { 
     _userService = userService; 
    } 

    public UserRoles GetRoles() { 
     return _userService.GetUserPermission().GetRoles(); 
    } 
} 

Jetzt weder die ApplicationUser noch die Database Klasse befassen sich mit dieser Leistungsoptimierung, was eine gute Sache ist. Der Decorator ermöglicht es uns, diese Leistungsoptimierung zu plugintieren, ohne die vorhandenen Klassen ändern zu müssen.