2014-09-19 51 views
1

我在設置屬性類的值時使用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():

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

+0

對於未來的讀者:答案修復了崩潰,但Moq仍然在分配值的方式。 – 2014-09-19 15:30:32

回答

1

我的猜測:由

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

的問題是替換

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

iDbSet.PropertyType等於IDbSet<XXX>。 因此,​​創建一個FakeDbSet<IDbSet<XXX>>,而您期待FakeDbSet<XXX>

+0

優秀的捕獲,它不再崩潰,但屬性也沒有設置。一名頭腦scrat,的人,我認爲這與Moq有關,但這不應該是一個問題。 – 2014-09-19 15:03:30

+0

在這種情況下,這不是同一個問題! – Olivier 2014-09-19 15:07:03

+0

你的屬性設置器可能是空的,例如...嘗試檢查iDbSet.GetGetMethod()。GetMethodBody()。GetILAsByteArray()。Length ...如果它小於4個字節長,那麼你的setter什麼都不做:) – Olivier 2014-09-19 15:08:52