使用反射来设置接口成员

本文关键字:接口 成员 设置 反射 | 更新日期: 2023-09-27 18:23:39

当类中的属性类型为和接口时,使用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>