samedi 12 novembre 2016

(C# .Net Core) Using Reflection To Instantiate a class from an external Assembly

I am currently trying to develop a method of running test classes in external projects programmatically using reflection. Here is a simplified chunk of code that should showcase my problem.

string pathToDLL = @"C:\Path\To\Test\Project\UnitTests.dll";
IEnumerable<Type> testClasses = assembly.GetExportedTypes();
Type testClass = testClasses.First();
object testClassInstance = assembly.CreateInstance(testClass.FullName); 

This code throws the following exception:

'assembly.CreateInstance(testClass.FullName)' threw an exception of type 'System.Reflection.TargetInvocationException'
    Data: {System.Collections.ListDictionaryInternal}
    HResult: -2146232828
    HelpLink: null
    InnerException: {System.IO.FileNotFoundException: Could not load file or assembly 'Project.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
File name: 'Project.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
   at Project.UnitTests.TestClass..ctor()}
    Message: "Exception has been thrown by the target of an invocation."
    Source: "System.Private.CoreLib"
    StackTrace: "   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)\r\n   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)\r\n   at System.Activator.CreateInstance(Type type, Boolean nonPublic)\r\n   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)\r\n   at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)\r\n   at System.Reflection.Assembly.CreateInstance(String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)\r\n   at System.Reflection.Assembly.CreateInstance(String typeName)"

In the stack trace it states that it "Could not load file or assembly 'Project.Core...'".

This project is one that the target DLL references directly (one that it tests). Does anyone know why this won't be able to pick up these DLLs automatically?


I've investigated ways of solving this problem:

1) It could be the way that the dlls have been compiled - this can be changed as I am in control of this - which is currently by running dotnet build */*/project.json at solution level. This successfully compiles everything, and all of the relevant DLLs seem to be populated in the bin folder. I've also investigated whether or not changing to dotnet publish or dotnet build */*/project.json --configuration Release though neither seem to have helped.

2) I've also looked into using different methods of compilation like Activator.CreateInstance again no dice.

3) I don't seem to see a way to load multiple DLLs into the same Assembly class so that I can control the references. Since AppDomains have been removed from .Net Core this doesn't look like it is possible, though I may be mistaken/looking in the wrong area.


If what I'm doing doesn't seem like it will be possible, does anyone know if this kind of functionality can be achieved using a different method? I.e. Roslyn?





Aucun commentaire:

Enregistrer un commentaire