I’m working on a C# application that is supposed to examine other C# executables and assert, via unit tests, certain properties about the interfaces they expose. (For context, this is a grading application for a CS course; the assignment is to parse numeric ranges from a text file and return them according to a fixed interface.)
So far, I’ve managed to:
- Load the executable as a variable
assembly, usingAssembly.LoadFrom(string) - Get the type of the interface in question, using
assembly.GetType(string) - Find an implementing type for the interface, again with
assembly.getType(string) - Instantiate the implementing type into a
dynamicobject, usingtype.GetConstructor(Type[])andconstructor.Invoke(Object[])
At this point, I have a dynamic object loader that I know implements the interface I’m testing. I want to call one of the interface methods on obj, so I run:
dynamic rangeSet = loader.GetRangeSetFromFile (inputFile); // inputFile is a string
This throws an InvalidCastException with the following trace:
System.InvalidCastException : Cannot cast from source type to destination type.
at SwapAssignment3.Implementations.RangeLoaderAdapter.GetRangeSetFromFile (string) <IL 0x0001e, 0x00066>
at (wrapper dynamic-method) object.CallSite.Target (System.Runtime.CompilerServices.Closure,System.Runtime.CompilerServices.CallSite,object,string) <IL 0x00036, 0x0007b>
at System.Dynamic.UpdateDelegates.UpdateAndExecute2<object, string, object> (System.Runtime.CompilerServices.CallSite,object,string) <0x003cf>
at AssignmentTests.R3Test.TestLoadingViaInterface () [0x00054] in /Users/tim/Dropbox/Courses/CSSE375-TA/AssignmentTests/AssignmentTests/R3Test.cs:82
at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) <0x00003>
at System.Reflection.MonoMethod.Invoke (object,System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo) <IL 0x000db, 0x00147>
Why would this error be thrown? Running the executable in question works just fine on its own; this error is only thrown in the context of my testing application. The body of the GetRangeSetFromFile method is as follows:
public IRangeSet GetRangeSetFromFile(string filePath)
{
var newRange = new RangeStorage();
_fileProcessor.ProcessFile(filePath);
newRange.StoreElements((List<IRange>) _fileProcessor.GetStorage());
return newRange;
}
I have good reason to believe (from the program output, among other things) that the cast error is being raised from the third line, with the List<IRange> cast; however, since the trace gives IL locations, I’m not 100% sure of this, and I don’t know why that cast would fail in the first place, since it works fine if the program is run on its own (outside my tester).
My primary question is: why is this cast error being raised, and how can I avoid it?
Edit: by request, the test code amounts to the following:
Type interfaceType = assembly.GetType("IRangeLoader");
List<Type> implementingTypes = new List<Type> (assembly.GetTypes ())
.FindAll ((Type t) => t.IsClass)
.FindAll ((Type t) => (new List<Type> (t.GetInterfaces ())).Contains (interfaceType));
Type implementingType = implementingTypes[0];
ConstructorInfo ctor = implementationType.GetConstructor (new Type[] {});
dynamic loader = ctor.Invoke (new Object[] {});
dynamic rangeSet = loader.GetRangeSetFromFile ("sample range.txt");
Ok, the following code seemed to work in invoking the method in another assembly:
Try using some of this. I was able to call into that object and then get the result from that method back.