2014-11-15 25 views
1

这可能以前被问过,但我不能解决它。也许如果我能得到正确的头衔,我可以把它放在一边。如何设置一个类型的约束,所以它必须是另一种通用类型的类型

我有这个通用库接口:

public interface IRepository<TEntity> 
{ 
    TEntity Resolve<TEntity>(); // dummy function, just to get the idea 
} 

我也有工作的通用单位,这是能够解决通用的存储库:

public interface IUnitOfWork 
{ 
    IRepository<TEntity> GetGenericRepository<TEntity>() where TEntity : class; 
} 

到目前为止好。

但随着现实生活的继续,我想创建一个自定义存储库,并具有一些特定的功能。所以我在想:继承;像这样:

public class SpecialRepository : IRepository<SomeEntityType> 
{ 
    public void SomeSpecialFunction() { }; 
} 

显然,这种类型不能与GetGenericRepository梅索德所以我想解决:让我们添加一个额外的方法将IUnitOfWork接口:

public interface IUnitOfWork 
{ 
    //same old get generic repository 
    IRepository<TEntity> GetGenericRepository<TEntity>() where TEntity : class; 

    //the newly added. 
    T GetInheretedRepository<T>() where T : class; 
} 

我希望能够调用工作单位有特殊的仓库,这样的事情:

public test() 
{ 
    IUnitOfWork uow = new UnitOfWork(); 

    //I want to make this call with a constraint on TemplateRepo 
    //to enforce it's type: IRepository<T> (which TemplateRepo is) 
    var y = uow.GetInheretedRepository<TemplateRepo>(); 
} 

的问题是:如何将T GetInheretedRepository<T>() where T : class;中的类型T限制为类型:IRepository<TEntity>

我尝试这样:

public interface IUnitOfWork 
{ 
    //the newly added. 
    //error: Only class or interface could be specified as constraint 
    T GetInheretedRepository<T>() where T : class, IRepository;  } 

public interface IUnitOfWork 
{ 
    //the newly added. 
    //error: type argument missing 
    T GetInheretedRepository<T>() where T : class, IRepository<>; 
} 

是不工作。

我可以删除约束作为一个快速修复或可能创建一个继承的工作单元,但然后;问题依然存在。

回答

1

您需要指定这样的编译罚款

public interface IUnitOfWork 
{ 
    //the newly added. 
    T GetInheretedRepository<T, TEntity>() where T : class, IRepository<TEntity>; 
} 

public interface IRepository<TEntity> 
{ 
    TEntity Resolve(); // dummy function, just to get the idea 
} 

例如第二类 - https://dotnetfiddle.net/MmmPil

2

做,这是通过添加第二个泛型类型参数的方式,具体如下:

TRepository GetInheretedRepository<TRepository, TEntity>() 
    where TRepository : IRepository<TEntity> 
    where TEntity : class; 

这里您提供存储库类型和实体类型。这样C#编译器可以检查类型是否匹配。以下是如何调用它:

var rep = uow.GetInheretedRepository<SpecialRepository, SomeEntityType>(); 

rep.SomeSpecialFunction(); 

这显然很糟糕,因为您必须指定两种类型。但更重要的是,这很糟糕,因为你必须指定具体类型,使你的代码依赖于具体类型;违反了Dependency Inversion Principle

我真的很想建议您离开一个设计,这个设计需要一个具体的类型,或者甚至更好,远离在特定存储库类上有很多方法的设计,因为这违反了SRPOCPISP,这可能会在稍后导致维护问题。

因此,请查看this article中描述的应用程序设计。

+0

尽管我将其他答案标记为“答案”,但我正在调整您在文章中描述的模式。我在基于MSMQ的环境中使用过类似的东西,但从未在数据层级使用过。听起来很有希望。 :-) – Stefan

相关问题