2010-11-02 14 views
0

Je sais que pour StructureMap vous pouvez enregistrer les types génériques en spécifiant les éléments suivants:construction personnalisée avec les génériques ouverts dans StructureMap

StructureMapConfiguration 
    .For(typeof(IRepository<>)) 
    .Use(typeof(RepositoryImplementation<>)); 

Lorsque ObjectFactory.GetInstance<IRepository<Entity>>() est appelée la mise en œuvre correspondant est retourné RepositoryImplementation<Entity>.

Mais que se passe-t-il si je veux une version encapsulée du référentiel? Une version qui implémente également IRepository<Entity> - disons CachedRepository<Entity> qui a un constructeur qui prend une implémentation de IRepository<TEntity> ctor: CachedRepository(IRepository<Entity> innerRepository).

Comment obtenir structuremap pour retourner CachedRepository<Entity> lorsque vous demandez un IRepository avec le concreate RepositoryImplementation comme innerRepository?

Répondre

1

Une approche est de créer un intercepteur de type personnalisé:

public class CacheMyRepos : TypeInterceptor 
{ 
    private readonly Type _openTargetType; 
    private readonly Type _openWrapperType; 

    public CacheMyRepos(Type openTargetType, Type openWrapperType) 
    { 
     _openTargetType = openTargetType; 
     _openWrapperType = openWrapperType; 
    } 

    public object Process(object target, IContext context) 
    { 
     var closedWith = target.GetType().GetGenericArguments()[0]; 
     var closedWrapperType = _openWrapperType.MakeGenericType(closedWith); 
     return Activator.CreateInstance(closedWrapperType, target); 
    } 

    public bool MatchesType(Type type) 
    { 
     return type.ImplementsInterfaceTemplate(_openTargetType); 
    } 
} 

Et puis l'enregistrer avec:

var container = new Container(x => 
{ 
    x.For(typeof (IRepository<>)).Use(typeof (RepositoryImplementation<>)); 
    x.RegisterInterceptor(
     new CacheMyRepos(typeof(IRepository<>), typeof(CachedRepository<>))); 
}); 
0

Est-ce que CachedRepository<Entity> doit fonctionner avec n'importe quelle implémentation concrète, ou est-il sûr de l'attacher à RepositoryImplementation<Entity>? Si elle peut être liée, cela devrait faire l'affaire:

StructureMapConfiguration 
    .For(typeof(IRepository<>)) 
    .Use(typeof(CachedRepository<>)); 

Ensuite, changez le constructeur de CachedRepository à CachedRepository(RepositoryImplementation<Entity> innerRepository).

+0

Je voudrais garder l'interface dans le constructeur. En faisant cela, je peux ajouter plus tard d'autres couches de logique au référentiel. I.e CachedRepository -> NotifyingRepository -> LoggingRepository -> TimingRepository -> ActualRepositoryImplementation. En faisant cela, je peux garder la logique séparée de ma mise en œuvre réelle du référentiel –