请注意,尽管提到了RhinoMocks,但唯一具体的部分是
GenerateStub
,该部分在提供的类型周围创建具体实现;其余部分与RhinoMocks无关。
通常情况下,泛型类型参数是在编译时解析的,这意味着您无法在不使用反射的情况下以内联方式输入类型作为泛型参数(例如:
var list = new List<typeof(int)>();
)。
然而,您可以使用反射来创建泛型类型。实际上,如果您可以从以下内容中获取动态代理的类型:
var entityMock = MockRepository.GenerateMock<IEntity>();
var dynamicType = entityMock.GetType();
MockRepository
有一个GenerateStub
方法,它需要一个Type
和object[]
作为参数。继续上面的内容:
var cacheType = typeof(Cache<>);
var genericType = cacheType.MakeGenericType(dynamicType);
var stubbed = MockRepository.GenerateStub(genericType, null);
stubbed
项目的类型不幸是
object
,但正如Lucero在评论中所述,可以使用通用型协变来获得比
object
更可用的类型。我在下面演示了这一点。
基于与Lucero的有趣讨论,如果您定义一个新的
ICache<out T>
接口来表示缓存,通用型协变将允许您将结果代理转换为基本类型(
ICache<IEntity>
)。
class Program
{
static void Main(string[] args)
{
IEntity entityMock = MockRepository.GenerateMock<IEntity>();
entityMock.Stub(s => s.Name).Return("Adam");
Type dynamicType = entityMock.GetType();
Type cacheType = typeof(ICache<>);
Type genericType = cacheType.MakeGenericType(dynamicType);
object stubbed = MockRepository.GenerateStub(genericType, null);
ICache<IEntity> typedStub = (ICache<IEntity>)stubbed;
typedStub.Stub(s => s.Item).Return(entityMock);
Console.WriteLine(typedStub.Item.Name);
Console.ReadLine();
}
}
public interface ICache<out T>
{
T Item { get; }
}
public interface IEntity
{
string Name { get; }
}