C#:反射实例化对象会引发转换错误?

标签 c# unit-testing exception reflection casting

我正在开发一个 C# 应用程序,该应用程序应该检查其他 C# 可执行文件,并通过单元测试断言有关它们公开的接口(interface)的某些属性。 (就上下文而言,这是一个 CS 类(class)的评分应用程序;作业是从文本文件中解析数字范围并根据固定接口(interface)返回它们。)

到目前为止,我已经做到了:

  • 将可执行文件加载为变量 assembly ,使用Assembly.LoadFrom(string)
  • 使用 assembly.GetType(string) 获取相关接口(interface)的类型
  • 再次使用 assembly.getType(string) 查找接口(interface)的实现类型
  • 将实现类型实例化为 dynamic对象,使用 type.GetConstructor(Type[])constructor.Invoke(Object[])

此时,我有一个 dynamic对象loader我知道实现了我正在测试的接口(interface)。我想调用 obj 上的接口(interface)方法之一,所以我运行:

dynamic rangeSet = loader.GetRangeSetFromFile (inputFile); // inputFile is a string

这会抛出 InvalidCastException具有以下跟踪:

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>

为什么会抛出这个错误?运行有问题的可执行文件本身就可以正常工作;此错误仅在我的测试应用程序的上下文中抛出。正文GetRangeSetFromFile方法如下:

public IRangeSet GetRangeSetFromFile(string filePath)
{
    var newRange = new RangeStorage();
    _fileProcessor.ProcessFile(filePath);
    newRange.StoreElements((List<IRange>) _fileProcessor.GetStorage());
    return newRange;
}

我有充分的理由相信(从程序输出等),强制转换错误是从第三行引发的,List<IRange> throw ;然而,由于跟踪给出了 IL 位置,所以我不能 100% 确定这一点,而且我不知道为什么该转换首先会失败,因为如果程序单独运行(在我的外部),它就可以正常工作。测试员)。

我的主要问题是:为什么会引发此转换错误,以及如何避免它?

编辑:根据请求,测试代码如下:

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

最佳答案

好的,下面的代码似乎可以在另一个程序集中调用该方法:

Assembly testAssembly = Assembly.LoadFile(<path>);

var interfaceType = testAssembly.GetTypes().Where(x => x.Name == "ISampleInterface").FirstOrDefault();

if(interfaceType != null)
{
    var implementingType = testAssembly.GetTypes().Where(typ => type.GetInterfaces().Any(iface => iface == interfaceType)).FirstOrDefault();

    if(implementingType != null)
    {
        dynamic obj = Activator.CreateInstance(implementingType);

        dynamic result = obj.SampleInterfaceMethod();

        Console.WriteLine(result);
    }
}

尝试使用其中的一些。我能够调用该对象,然后从该方法获取结果。

关于C#:反射实例化对象会引发转换错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10436274/

相关文章:

c# - .NET 中的 WebClient 和 HTTPWebRequest 类之间有什么区别?

c# - 以编程方式安装 Windows 服务

c++ - 关于 RAII,C++ `try`/`catch` block 是否与其他 block 相同?

c# - 如何在代码中设置 DataGridTextColumn 的绑定(bind)?

c# - 单元测试 Controller 中抛出的异常

javascript - 使用 Vue Js 运行 Jest 测试时出现 "SyntaxError: Cannot use import statement outside a module"

java - 使用 Mockito 模拟的 Runnable 创建线程

python:如果finally block 引发异常,则从try block 中恢复异常

objective-c - iOS, objective-c 在一开始就抛出异常

c# - 向具有标识主键的 sql 数据库添加一行