C# Can';t让Rhinomock发出遵循泛型类型限制规则的模拟

C# Can';t让Rhinomock发出遵循泛型类型限制规则的模拟,c#,rhino-mocks,C#,Rhino Mocks,因此,使用NUnit和Rhinomock: //Defines basic behavior of all persistable domain objects public interface IDomainObject {...} //defines domain objects specific to the Security DB public interface ISecurityDomainObject : IDomainObject {...} //Defines a basi

因此,使用NUnit和Rhinomock:

//Defines basic behavior of all persistable domain objects
public interface IDomainObject {...}

//defines domain objects specific to the Security DB
public interface ISecurityDomainObject : IDomainObject {...}

//Defines a basic transactional data Repository; there are multiple implementors
//which each close TRest to the interface that defines their DB's domain classes
public interface IRepository<TRest> : IDisposable where TRest:IDomainObject
{
    IUnitOfWork BeginUnitOfWork();
    void CommitUnitOfWork(IUnitOfWork unitOfWork);
    void RollBackUnitOfWork(IUnitOfWork unitOfWork);        
    void Save<T>(T domainObject, IUnitOfWork unitOfWork) where T : class, TRest;        
    IQueryable<T> QueryFor<T>(IUnitOfWork unitOfWork) where T :class, TRest;
}

public interface ISecurityRepository:IRepository<ISecurityDomainObject> {}

public class SecurityRepository:ISecurityRepository

...

//This line breaks when run in an NUnit test
var securityRepository = MockRepository.GenerateMock<ISecurityRepository>();
...
//定义所有持久化域对象的基本行为
公共接口IDOMAIN对象{…}
//定义特定于安全数据库的域对象
公共接口ISecurityDomainObject:IDomainObject{…}
//定义一个基本的事务数据存储库;有多个实现者
//每个数据库都关闭定义其DB域类的接口
公共接口IRepository:IDisposable其中TRest:IDomainObject
{
i工作开始工作();
无效委托工作(i工作单元);
无效回滚unitOfWork(IUnitOfWork unitOfWork);
void Save(T domainObject,IUnitOfWork unitOfWork),其中T:class,TRest;
(IUnitOfWork unitOfWork)的可查询查询,其中T:class,TRest;
}
公共接口ISecurityRepository:IRepository{}
公共类SecurityRepository:ISecurityRepository
...
//在NUnit测试中运行时,此行中断
var securityRepository=MockRepository.GenerateMock();
...
我得到的错误是:

System.TypeLoadException : Method 'Save' on type 'ISecurityRepositoryProxyb8e21deb3cb04067a01ac5b63f7045af' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' tried to implicitly implement an interface method with weaker type parameter constraints.
at System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule module, Int32 tk, ObjectHandleOnStack type)
at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
at System.Reflection.Emit.TypeBuilder.CreateType()
at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType()
at Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.GenerateCode(Type proxyTargetType, Type[] interfaces, ProxyGenerationOptions options)
at Castle.DynamicProxy.DefaultProxyBuilder.CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, IInterceptor[] interceptors)
at Rhino.Mocks.MockRepository.MockInterface(CreateMockState mockStateFactory, Type type, Type[] extras)
at Rhino.Mocks.MockRepository.CreateMockObject(Type type, CreateMockState factory, Type[] extras, Object[] argumentsForConstructor)
at Rhino.Mocks.MockRepository.DynamicMock(Object[] argumentsForConstructor)
at Rhino.Mocks.MockRepository.<>c__DisplayClass7`1.<GenerateMock>b__6(MockRepository r)
at Rhino.Mocks.MockRepository.CreateMockInReplay(Func`2 createMock)
at Rhino.Mocks.MockRepository.GenerateMock(Object[] argumentsForConstructor)
at CSHD.Tests.Unit.Presentation.LoginTests.TestAuthenticationFails() in LoginTests.cs: line 138 
System.TypeLoadException:程序集“DynamicProxyGenAssembly2,版本=0.0.0.0,区域性=中性,PublicKeyToken=null”中类型“ISecurityRepositoryProxyb8e21deb3cb04067a01ac5b63f7045af”的方法“保存”试图隐式实现具有较弱类型参数约束的接口方法。
位于System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule模块,Int32 tk,ObjectHandleOnStack类型)
在System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()中
在System.Reflection.Emit.TypeBuilder.CreateType()处
在Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType()中
在Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.GenerateCode(类型proxyTargetType,类型[]interfaces,ProxyGenerationOptions)
在Castle.DynamicProxy.DefaultProxyBuilder.CreateInterfaceProxyTypeWithoutTarget上(输入interfaceToProxy,输入[]additionalInterfacesToProxy,ProxyGenerationOptions)
在Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyTypeWithoutTarget(输入interfaceToProxy,输入[]additionalInterfacesToProxy,ProxyGenerationOptions)
在Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(类型interfaceToProxy,类型[]additionalInterfacesToProxy,ProxyGenerationOptions,IInterceptor[]拦截器)
位于Rhino.Mocks.MockRepository.MockInterface(CreateMockState-mockStateFactory,Type-Type,Type[]extras)
位于Rhino.Mocks.MockRepository.CreateMockObject(类型,CreateMockState工厂,类型[]附加,对象[]argumentsForConstructor)
位于Rhino.Mocks.MockRepository.DynamicMock(对象[]argumentsForConstructor)
在Rhino.Mocks.MockRepository.c_uuu显示类7`1.b_uuuu6(mockr存储库)
在Rhino.Mocks.MockRepository.CreateMockInReplay(Func`2 createMock)中
位于Rhino.Mocks.MockRepository.GenerateMock(对象[]argumentsForConstructor)
在LoginTests.cs中的CSHD.Tests.Unit.Presentation.LoginTests.TestAuthenticationFails()处:第138行
当试图针对具体类生成mock时,我得到了一个类似的错误,这次是在QueryFor()方法上。如果我尝试重新定义在ISecurityRepository接口中使用TRest的方法,我会得到一个“System.BadImageFormatException:试图加载格式不正确的程序。(HRESULT中的异常:0x8007000B)”,这看起来像是一个倒退


我认为核心问题是Rhinomock被用作泛型类型限制的泛型参数弄糊涂了。我不知道它到底在哪里被混淆,因此我不知道如何或是否可以使用它。我有足够的集成测试覆盖率,如果必须的话,我可以忽略这些失败的单元测试,但显然,如果可以的话,我宁愿修复它们。您的想法?

看起来Castle Dynamic Proxy(Rhino Mocks用于代理生成)没有按照您定义泛型参数的方式正确生成代理类。如果您这样定义IRepository,则可以生成代理(并因此生成模拟):

public interface IRepository<T> : IDisposable where T : class, IDomainObject
{
    IUnitOfWork BeginUnitOfWork();
    void CommitUnitOfWork(IUnitOfWork unitOfWork);
    void RollBackUnitOfWork(IUnitOfWork unitOfWork);        
    void Save(T domainObject, IUnitOfWork unitOfWork);        
    IQueryable<T> QueryFor(IUnitOfWork unitOfWork);
}
公共接口IRepository:IDisposable其中T:class,IDomainObject
{
i工作开始工作();
无效委托工作(i工作单元);
无效回滚unitOfWork(IUnitOfWork unitOfWork);
void Save(T域对象,IUnitOfWork unitOfWork);
可查询的查询(IUnitOfWork unitOfWork);
}

如果您真的需要以另一种方式定义它,那么您必须向Rhino Mocks提交一个bug。

这似乎是由Castle.DynamicProxy引起的一个已知问题,该问题已在该项目的最新主干中修复,但在最新Rhino Mocks版本中仍然存在:


如果你喜欢冒险,你可以用最新的DynamicProxy制作你自己的犀牛模型,它应该是固定的。

我真的有点需要按照我的方式定义它。我有几个IRepository的实现,每个实现都针对不同的DB(我没有组成模式,我只是继承了它),每个实现都针对域的不同子集。我的定义确保了代码在编译时不会试图要求存储库处理不属于其模式的对象。您所拥有的基本上是每个域对象都需要一个存储库,因为T不能定义为ISecurityDomainObject,因为Save和QueryFor无法知道具体的类型(它们需要)。这很公平。问题是,这种例外情况并没有发生在犀牛模型中,而是发生在Castle DynamicProxy中。我检查了Moq(它使用了比Rhino MOCKS更新版本的Castle DynamicProxy),它也受到了这个限制。目前,使用Rhino Mock或Moq无法模拟此接口。为了解决这个问题,Castle DynamicProxy必须解决根本问题。希望我能给你一个更好的答案。谢谢。我想我现在就不考虑考试了,注意一下