当类中的属性类型为和接口时,使用PropertyInfo.SetValue设置该属性的值时遇到问题。这段代码是用于单元测试的,我想用它来伪造实体中的IDbSet。
public static void AddFakeDbSets<T>(this Mock<T> obj) where T : class
{
var iDbSets = typeof(T).GetProperties().Where(p =>
p.PropertyType.IsGenericType == true &&
p.PropertyType.GetGenericTypeDefinition().Name.StartsWith("IDbSet"));
Type baseType = typeof(FakeDbSet<>);
foreach (var iDbSet in iDbSets)
{
if (iDbSet.GetValue(obj.Object) == null)
{
var genericType = baseType.MakeGenericType(iDbSet.PropertyType);
var concreteObject = Activator.CreateInstance(genericType);
iDbSet.SetValue(obj.Object, concreteObject);
}
}
}
具体来说,它在iDbSet.SetValue()上崩溃,并出现以下错误:
类型为的对象'lnEcommAPI.Tests.FakeDbSet
1[System.Data.Entity.IDbSet
1[LNWebServicesPositiony.WhatsNew]]'无法转换为类型'System.Data.Entity.IDbSet `1[LNWebServicesPositiony.WhatsNew]'.
我的猜测:替换
var genericType = baseType.MakeGenericType(iDbSet.PropertyType);
通过
var genericType = baseType.MakeGenericType(iDbSet.PropertyType.GetGenericArguments()[0]);
问题是iDbSet.PropertyType
等于IDbSet<XXX>
。因此,typeof(FakeDbSet<>).MakeGenericType(iDbSet.PropertyType)
创建一个FakeDbSet<IDbSet<XXX>>
,而您期望的是FakeDbSet<XXX>