在StructureMap中使用开放式泛型进行自定义构造

时间:2010-11-02 16:28:07

标签: .net generics structuremap

我知道对于structuremap,您可以通过指定以下内容来注册泛型类型:

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

调用ObjectFactory.GetInstance<IRepository<Entity>>()时,将返回相应的实现RepositoryImplementation<Entity>

但是,如果我想要一个包装版本的存储库怎么办?一个同样实现IRepository<Entity>的版本 - 让我们说CachedRepository<Entity>有一个构造函数,它实现IRepository<TEntity> ctor:CachedRepository(IRepository<Entity> innerRepository)

当要求使用concreate RepositoryImplementation作为innerRepository的IRepository时,如何让structuremap返回CachedRepository<Entity>

2 个答案:

答案 0 :(得分:1)

一种方法是创建自定义类型拦截器:

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

然后注册:

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

答案 1 :(得分:0)

CachedRepository<Entity>是否必须使用任何具体实现,或者将其绑定到RepositoryImplementation<Entity>是否安全?如果它可以绑定,这应该可以解决问题:

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

然后将CachedRepository构造函数更改为CachedRepository(RepositoryImplementation<Entity> innerRepository)