2012-08-16 53 views
1

雖然有助於OSS project工作,但我正在運行TypeLoadException。我正在創建一個縫,開發人員可以注入他們自己的Repository類來刪除EF上的具體依賴關係,這樣我就可以隔離我的新代碼並運行一些測試。動態實例化一個嵌套類型爲arg的對象時引發TypeLoadException

看來,針對具有嵌套類型arg的類型運行Activator.CreateInstance()會在運行時引發一個扳手。我以前使用過這種模式很多次,但這次不同的是我使用它來動態注入一個通用的Repository模式實現。這個問題似乎與該類型的arg有關。我目前難住,所以任何幫助將不勝感激。

這裏是我得到的錯誤:

System.TypeLoadException: Could not load type 'Rock.Tests.Fakes.FakeRepository' from assembly 'Rock.Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. 
    at System.Reflection.RuntimeAssembly.GetType(RuntimeAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type) 
    at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase) 
    at System.Activator.CreateInstance(String assemblyName, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, Evidence securityInfo, ref StackCrawlMark stackMark) 
    at System.Activator.CreateInstance(String assemblyName, String typeName) 
    at Rock.Data.RepositoryFactory`1.FindRepository() in RepositoryFactory.cs: line 30 
    at Rock.Data.Service`1..ctor() in Service.cs: line 34 
    at Rock.Core.AttributeService..ctor() 
    at Rock.Attribute.Helper.LoadAttributes(IHasAttributes item) in Helper.cs: line 165 
    at Rock.Data.ModelWithAttributes`1.get_Attributes() in ModelWithAttributes.cs: line 38 
    at Rock.CMS.Page.MapPagesRecursive(Page page) in Page.cs: line 422 
    at Rock.CMS.Page.ExportObject() in Page.cs: line 410 
    at Rock.Tests.CMS.PageTests.TheExportObjectMethod.ShouldCopyPropertiesOfDTO() in PageTests.cs: line 16 

下面是一些有關(註釋)代碼從Rock.Data命名空間中的片段:

IRepository.cs

public interface IRepository<T> where T : class 
{ 
    // Very basic CRUD repository contract... 
} 

個EFRepository.cs

public class EFRepository<T> where T : Model<T> 
{ 
    // Concrete implementation of IRepository<T> specific to Entity Framework 4.3 
} 

Service.cs

public class Service<T> where T : Model<T> 
{ 
    private readonly IRepository<T> _repository; 

    // Inside this constructor are my changes... 
    public Service() // : this(new EFRepository<T>()) 
    { 
     // Instead of hard-coding the use of EFRepository here, I 
     // thought it might be worthwhile to add a call out to a 
     // factory method implementation. 

     var factory = new RepositoryFactory<T>(); 
     _repository = factory.FindRepository(); 
    } 

    // This constructor never really appears to be called. 
    // From my test code's entry point, there's no way for me to 
    // explicitly call this constructor, hence the factory implemenation. 
    public Service(IRepository<T> repository) 
    { 
     _repository = repository; 
    } 
} 

RepositoryFactory.cs

// Here's my quick/dirty factory method implementation to try to generically 
// instantiate an IRepository of my choosing for testing purposes... 
public class RepositoryFactory<T> where T : Model<T> 
{ 
    public IRepository<T> FindRepository() 
    { 
     var repositoryTypeSetting = ConfiguraitonManager.AppSettings["RepositoryType"]; 

     if (string.IsNullOrEmpty(repositoryTypeSetting)) 
     { 
      return new EFRepository<T>(); 
     } 

     var settingArray = repositoryTypeSetting.Split(new[] { ',' }); 

     // I'm aware that Trim() is superfluous here, but this will be part of a development 
     // framework, so I'm trying to take whitespace/developer error into account. 
     var className = settingArray[0].Trim(); 
     var assemblyName = settingArray[1].Trim(); 

     // I've tried with and without Unwrap(), the exception originates from Activator.CreateInstance() 
     return (IRepository<T>) Activator.CreateInstance(assemblyName, className).Unwrap(); 
    } 
} 

下面是一些假冒的對象和測試代碼片段我的m在我單獨的Rock.Tests項目中使用......

FakeRepository.cs

// Basic fake/stub implementation 
public class FakeRepository<T> : IRepository<T> where T : Model<T> 
{ 
    // Nothing here yet other than `throw new NotImplementedException()` for each method in the contract 
    // We never make it here... 
} 

PageTests.cs

// Very basic XUnit test example... 
public class PageTests 
{ 
    public class TheExportMethod 
    { 
     [Fact] 
     public void ShouldNotBeEmpty() 
     { 
      var page = new Page { Name = "FooPage" }; 
      var result = page.Export(); 
      Assert.NotEmpty(result); 
     } 
    } 
} 

的App.config

<configuration> 
    <appSettings> 
     <clear/> 
     <add key="RepositoryType" value="Rock.Tests.Fakes.FakeRepository,Rock.Tests"/> 
    </appSettings> 
</configuration> 

Hopef這是涵蓋它非常徹底。提前致謝!

+0

所有的代碼真的有關嗎?你能以某種方式縮短這個嗎?大約一半的時候,我的眼睛眯起來。 – MikeKulls 2012-08-16 21:59:34

+0

大多數情況下,他們都是。主要是爲了幫助說明所涉及的限制。好的東西更接近底部(RepositoryFactory類)。 – JasonOffutt 2012-08-17 07:38:25

回答

1

它看起來像你試圖實例化一個開放的泛型類型,因爲你的配置文件沒有指定FakeRepository<T>的泛型類型參數。你需要做的更像:

<add key="RepositoryType" value="Rock.Tests.Fakes.FakeRepository`1[[Some.ModelType,Some.ModelAssembly]],Rock.Tests"/> 
+0

就是這樣!謝謝!解決了我的第一個問題,只是揭露了一個新問題。儘管如此,肯定會讓球再次滾動。再次感謝! – JasonOffutt 2012-08-20 15:59:15