Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有工作单元模式的泛型问题_C#_Design Patterns_Inversion Of Control_Repository Pattern_Unit Of Work - Fatal编程技术网

C# 具有工作单元模式的泛型问题

C# 具有工作单元模式的泛型问题,c#,design-patterns,inversion-of-control,repository-pattern,unit-of-work,C#,Design Patterns,Inversion Of Control,Repository Pattern,Unit Of Work,我需要一些关于工作单元+存储库+IoC模式设计的帮助。我有几个定义如下的接口: public interface IRepository<T> { T GetEntity(int id); } public interface IUserRepository : IRepository<User> { User GetUserByXyz(int id); } public interface IUnitOfWork { T

我需要一些关于工作单元+存储库+IoC模式设计的帮助。我有几个定义如下的接口:

public interface IRepository<T>
{       
    T GetEntity(int id);
}

public interface IUserRepository : IRepository<User>
{   
    User GetUserByXyz(int id);
}

public interface IUnitOfWork
{
    T Respository<T>() where T : IRepository<T>;
}
公共接口IRepository
{       
T GetEntity(int-id);
}
公共接口IUserRepository:IRepository
{   
用户GetUserByXyz(int-id);
}
公共接口工作单元
{
T Respository(),其中T:i pository;
}
我使用Unity来解决一些引用。以下是UoW的实施情况:

public class UnitOfWork : IUnitOfWork
{
    public T Respository<T>() where T : IRepository<T>
    {
        var container = new UnityContainer();
        return container.Resolve<T>();
    }
}
公共类UnitOfWork:IUnitOfWork
{
public T Respository(),其中T:i Respository
{
var container=new UnityContainer();
返回container.Resolve();
}
}
现在调用接口时遇到问题:

User user = _unitOfWork.Respository<IUserRepository>().GetUserByXyz(1);
User User=\u unitOfWork.Respository().GetUserByXyz(1);
类型“IUserRepository”不能用作中的类型参数“T” 泛型类型或方法“IUnitOfWork.Respository()”。没有 从“IUserRepository”到的隐式引用转换 “我相信”


如何避开常规约束错误?

您混淆了常规约束:

public T Respository<T,U>() where T : IRepository<U> 

User user = _unitOfWork.Respository<IUserRepository,User>().GetEntity(1);
public T Respository(),其中T:IRepository
User User=\u unitOfWork.Respository().GetEntity(1);

您对
i工作单元的定义似乎有点奇怪,而且您的通用参数约束似乎有误:

public interface IUnitOfWork
{
    T Respository<T>() where T : IRepository<T>;
}

关于我的评论:

语句
public T Respository(),其中T:IRepository
表示您期望的类型本身就是一个存储库,例如,IUserRepository必须是一个
IRepository
,才能满足您的条件

您需要两个不同的泛型,一个用于reportory
TItem
中保存的项目,另一个用于存储库本身
TRepo

然后整个代码变成:

public interface IRepository<TItem>
{       
    TItem GetEntity(int id);
}

public interface IUserRepository : IRepository<User>
{   
}

public interface IUnitOfWork
{
    TRepo Respository<TRepo,TItem>() where TRepo : IRepository<TItm>;
}
公共接口IRepository
{       
TItem-GetEntity(int-id);
}
公共接口IUserRepository:IRepository
{   
}
公共接口工作单元
{
TRepo Respository(),其中TRepo:i pository;
}

公共类UnitOfWork:IUnitOfWork
{
public TRepo Respository()其中TRepo:i Respository
{
var container=new UnityContainer();
返回container.Resolve();
}
}
最后,调用变为:

User user = _unitOfWork.Respository<IUserRepository,User>().GetEntity(1);
User=\u unitOfWork.Respository().GetEntity(1);

初始注释:


不需要第二个类型参数的替代解决方案:

我同意@Jon Egerton的观点,要使其正确工作,一个选项是引入第二个泛型类型参数(
TItem
,在
TItemRepository
旁边)。但是,还有另一种解决方案涉及到标记接口
IRepository

// non-generic marker interface (empty)
public interface IRepository {}

public interface IRepository<T> : IRepository { … /* as before */ }
//                              ^^^^^^^^^^^^^
//                                  added

public class UnitOfWork
{
    public TRepository Get<TRepository>() where TRepository : IRepository
                                       // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       // this way, no 2nd type parameter is
                                       // needed since the marker interface is
                                       // non-generic.
    { 
        return new UnityContainer().Resolve<TRespository>();
    }
}
//非通用标记接口(空)
公共接口IRepository{}
公共接口IRepository:IRepository{…/*与前面一样*/}
//                              ^^^^^^^^^^^^^
//增加
公营单位
{
public TRepository Get()其中TRepository:IRepository
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//这样,就不需要第二个类型参数
//需要,因为标记接口是
//非泛型。
{ 
返回新的UnityContainer().Resolve();
}
}

根据要求:工作单元示例:

如果你跟随,你会得到与你现在所得到的完全不同的东西。更确切地说,根据他自己的理解,一个工作单元仅仅跟踪对一组对象所做的所有更改。这背后的思想是,当通过工作单元对象请求时,更改不会一次一个地持久化(例如,保存到数据库),而是同时持久化;因此,模式的名称为:

class UnitOfWork<T>
{
    // the UnitOfWork object tracks changes to objects of type T:
    private HashSet<T> newItems;
    private HashSet<T> modifiedItems;
    private HashSet<T> removedItems;

    public void Commit()
    {
        // let's say items are persisted to an RDBMS, then:
        // * generate 'DELETE FROM [tableForItemsOfTypeT]' statements
        //   for all items in the 'removedItems' set;
        // * generate 'INSERT INTO [tableForItemsOfTypeT]' statements
        //   for all items in the 'newItems' set;
        // * generate 'UPDATE [tableForItemsOfTypeT]' statements
        //   for all items in the 'modifiedItems' set.
    }
}
工作单元类
{
//UnitOfWork对象跟踪对T类型对象的更改:
私有HashSet newItems;
私有哈希集修饰符;
私有HashSet-removedItems;
公共无效提交()
{
//假设项目被持久化到RDBMS,那么:
//*生成“从[tableForItemsOfTypeT]删除”语句
//对于“removedItems”集合中的所有项目;
//*生成“插入[tableForItemsOfTypeT]”语句
//对于“newItems”集合中的所有项目;
//*生成“UPDATE[tableForItemsOfTypeT]”语句
//对于“modifiedItems”集中的所有项。
}
}

IAccountRepository
来自哪里?这是上面代码示例中的一个输入错误,还是您在此处显示的代码不完整?这是一个输入错误-更新了原始帖子:)我怀疑这里有两个不同的泛型-一个是T:IRepository,一个是T:SomeOtherClass(例如User)。也许应该拆分为使用TItem和TRepo?我希望在子接口上调用该方法,例如GetUserByXyz。这就是为什么我试图将类型返回为T.Modified OP.i不确定是否滥用了工作单元模式,但使用UoW的原因是将所有存储库组合在一起,以便更容易管理对象状态。至于UoW是一个服务定位器——这部分是正确的,这就是为什么我在玩泛型并试图限制范围:)@Fixer,您只是通过提供一个“入口点”将它们按语法“分组”,从中可以要求存储库;但是真正的“分组”可能涉及组合,即在同一个类中有几个不同的
IRepository
字段或属性。我明白了-你介意给我一个简单的例子吗?抱歉,我是UoW的新手(你可能会说)@Fixer:我也不是这方面的专家(但我会尝试提供一个例子);我只是看到了你的解决方案中可能存在的一个缺陷。但是如果像
Repository()
这样的方法是什么呢
User user = _unitOfWork.Respository<IUserRepository,User>().GetEntity(1);
_unitOfWork.Respository<IUserRepository>()…
_unityContainer.Resolve<IUserRepository>()…
// non-generic marker interface (empty)
public interface IRepository {}

public interface IRepository<T> : IRepository { … /* as before */ }
//                              ^^^^^^^^^^^^^
//                                  added

public class UnitOfWork
{
    public TRepository Get<TRepository>() where TRepository : IRepository
                                       // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       // this way, no 2nd type parameter is
                                       // needed since the marker interface is
                                       // non-generic.
    { 
        return new UnityContainer().Resolve<TRespository>();
    }
}
class UnitOfWork<T>
{
    // the UnitOfWork object tracks changes to objects of type T:
    private HashSet<T> newItems;
    private HashSet<T> modifiedItems;
    private HashSet<T> removedItems;

    public void Commit()
    {
        // let's say items are persisted to an RDBMS, then:
        // * generate 'DELETE FROM [tableForItemsOfTypeT]' statements
        //   for all items in the 'removedItems' set;
        // * generate 'INSERT INTO [tableForItemsOfTypeT]' statements
        //   for all items in the 'newItems' set;
        // * generate 'UPDATE [tableForItemsOfTypeT]' statements
        //   for all items in the 'modifiedItems' set.
    }
}