C# 使用泛型和StructureMap实现策略模式

C# 使用泛型和StructureMap实现策略模式,c#,generics,dependency-injection,structuremap,C#,Generics,Dependency Injection,Structuremap,我正在尝试使用SM和泛型在我的存储库层中实现策略模式。为此,我有一个接口IPocoRepository,它有一个使用实体框架的具体实现。我已设法将其连接到我的引导程序文件中: For(typeof(IPocoRepository<>)).Use(typeof(EntityFrameworkRepository<>)); For(typeof(IPocoRepository))。使用(typeof(EntityFrameworkRepository)); 当我尝试为这个

我正在尝试使用SM和泛型在我的存储库层中实现策略模式。为此,我有一个接口IPocoRepository,它有一个使用实体框架的具体实现。我已设法将其连接到我的引导程序文件中:

For(typeof(IPocoRepository<>)).Use(typeof(EntityFrameworkRepository<>));
For(typeof(IPocoRepository))。使用(typeof(EntityFrameworkRepository));
当我尝试为这个接口实现缓存时,问题出现了。在我的缓存类中,我需要一个基本存储库类的实例,这样我就可以保持我的设计干净利落。让我概述一下这三个文件的外观:

public interface IPocoRepository<T>
{
    IQueryable<T> GetAll();
    ...


public class EntityFrameworkRepository<T> : IPocoRepository<T> where T : class
{
    public IQueryable<T> GetAll()
    {
        ...

public class CachedRepository<T> : IPocoRepository<T> where T : class
{
    private IPocoRepository<T> _pocoRepository;

    public CachedRepository(IPocoRepository<T> pr)
    {
        _pocoRepository = pr;
    }

    public IQueryable<T> GetAll()
    {
        var all = (IQueryable<T>)CacheProvider.Get(_cacheKey);
        if (!CacheProvider.IsSet(_cacheKey))
        {
            all = _pocoRepository.GetAll();
            ...
公共接口IPocoRepository
{
IQueryable GetAll();
...
公共类EntityFrameworkRepository:IPocoRepository其中T:class
{
公共IQueryable GetAll()
{
...
公共类CachedRepository:IPocoRepository,其中T:class
{
私人IPocoRepository(私人IPocoRepository);;
公共缓存存储(IPocoreposition pr)
{
_pocoRepository=pr;
}
公共IQueryable GetAll()
{
var all=(IQueryable)CacheProvider.Get(_cacheKey);
如果(!CacheProvider.IsSet(_cacheKey))
{
all=_pocoRepository.GetAll();
...
编辑:我希望StructureMap在请求IPocoRepository时返回CachedPository,但在CachedPository中请求时除外-然后我希望它返回EntityFrameworkRepository

我知道这在处理非泛型类时很简单:

For<ICountyRepository>().Use<CachedCountyRepository>()
.Ctor<ICountyRepository>().Is<CountyRepository>();
For()。使用()
.Ctor().Is();

我试图在文档中搜索如何执行此操作,但找不到任何内容。如有任何帮助,将不胜感激!

好的,这并不难。您可以使用类型拦截器。如果您有以下类:

public interface IRepository<T>{}

public class Repository<T>:IRepository<T>{}

public class RepositoryCache<T> : IRepository<T>
{
    private readonly IRepository<T> _internalRepo;

    public RepositoryCache(IRepository<T> internalRepo)
    {
        _internalRepo = internalRepo;
    }

    public IRepository<T> InternalRepo
    {
        get { return _internalRepo; }
    }
}
公共接口IRepository{}
公共类存储库:IRepository{}
公共类RepositoryCache:IRepository
{
私人只读易趣回购;
公共回购缓存(IRepository internalRepo)
{
_内部回购=内部回购;
}
公开回购
{
获取{return\u internalRepo;}
}
}
然后您需要创建一个类型拦截器。您可以使用可配置的“MatchedTypeInterceptor”StructureMap为此提供。拦截器将需要查找您的存储库,然后确定泛型类型参数是什么。拥有类型参数后,它可以声明所需的缓存类型并对其进行初始化。作为初始化的一部分,它将在其构造函数中获取原始存储库。然后tor将把完成的缓存返回到ioc上下文请求的任何缓存

这可以移到您的注册表中,我只是把它作为一个简单的例子放在一起

    [Test]
    public void doTest()
    {
        MatchedTypeInterceptor interceptor = new MatchedTypeInterceptor(
             x => x.FindFirstInterfaceThatCloses(typeof (IRepository<>)) != null);

        interceptor.InterceptWith(original =>
        {
            Type closedType = original.GetType()
                 .FindFirstInterfaceThatCloses(typeof(IRepository<>));

            var genericParameters = closedType.GetGenericArguments();

            var closedCacheType = typeof(RepositoryCache<>)
                 .MakeGenericType(genericParameters);

            return Activator.CreateInstance(closedCacheType, new[] {original});
        });

        ObjectFactory.Initialize(x =>
        {
            x.For(typeof (IRepository<>)).Use(typeof (Repository<>));
            x.RegisterInterceptor(interceptor);
        });

        var test = ObjectFactory.GetInstance<IRepository<int>>();

        Assert.That(test is RepositoryCache<int>);
    }
[测试]
公共空间doTest()
{
MatchedTypeInterceptor拦截器=新的MatchedTypeInterceptor(
x=>x.FindFirstInterfaceThatCloses(typeof(IRepository))!=null;
interceptor.InterceptWith(原始=>
{
Type closedType=original.GetType()
.FindFirstInterfaceThatCloses(类型为(IRepository));
var genericParameters=closedType.GetGenericArguments();
var closedCacheType=typeof(RepositoryCache)
.MakeGenericType(genericParameters);
返回Activator.CreateInstance(closedCacheType,new[]{original});
});
ObjectFactory.Initialize(x=>
{
x、 用于(typeof(IRepository))。使用(typeof(Repository));
x、 注册接收器(拦截器);
});
var test=ObjectFactory.GetInstance();
断言(测试是RepositoryCache);
}

那么,实际的问题是什么呢?在我看来,你似乎在试图复制像Castle Windsor这样的框架。我已经更新了这个问题;希望能更清楚地说明我的问题。我希望坚持使用StructureMap这是依赖项注入框架所做的,看看吧-这可能会很有意义。:)Related:这篇文章可能会有帮助:干得好!我在代码中对_internalRepo字段进行了测试,它确实是存储库的一个实例——这正是我想要的!非常感谢!)