Jonathan DeMarks
Jonathan DeMarks

Reputation: 2441

Using reflection to set an interface member

I'm having trouble setting the value of a property in a class when the property type is and interface using PropertyInfo.SetValue. This code is for unit testing which I'd like to use to fake out the IDbSets in my Entity.

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);
        }
    }
}

Specifically it crashes at iDbSet.SetValue() with the following error:

Object of type 'lnEcommAPI.Tests.FakeDbSet1[System.Data.Entity.IDbSet1[LNWebServicesRepository.WhatsNew]]' cannot be converted to type 'System.Data.Entity.IDbSet`1[LNWebServicesRepository.WhatsNew]'.

Upvotes: 2

Views: 971

Answers (1)

Olivier
Olivier

Reputation: 5688

My guess: replace

var genericType = baseType.MakeGenericType(iDbSet.PropertyType);

by

var genericType = baseType.MakeGenericType(iDbSet.PropertyType.GetGenericArguments()[0]);

The problem is that iDbSet.PropertyType is equal to IDbSet<XXX>. Thus, typeof(FakeDbSet<>).MakeGenericType(iDbSet.PropertyType) creates a FakeDbSet<IDbSet<XXX>>, while you're expecting a FakeDbSet<XXX>

Upvotes: 1

Related Questions