使用反射设置接口成员

时间:2014-09-19 14:44:14

标签: c# .net entity-framework reflection propertyinfo

当属性类型为和使用PropertyInfo.SetValue的接口时,我无法在类中设置属性的值。 此代码用于单元测试,我想用它来伪造我的实体中的IDbSets。

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()崩溃时出现以下错误:

  

类型的对象   &#39; {lnEcommAPI.Tests.FakeDbSet {1}} 1 [LNWebServicesRepository.WhatsNew]]&#39;   无法转换为类型   &#39; System.Data.Entity.IDbSet`1 [LNWebServicesRepository.WhatsNew]&#39;

1 个答案:

答案 0 :(得分:1)

我的猜测:替换

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>