2

私は、他のC#実行可能ファイルを調べ、単体テストを介して、それらが公開するインターフェイスに関する特定のプロパティをアサートすることになっているC#アプリケーションに取り組んでいます。(コンテキストとして、これはCSコースの評価アプリケーションです。割り当ては、テキストファイルから数値範囲を解析し、固定インターフェイスに従ってそれらを返すことです。)

これまでのところ、私は次のことに成功しました。

  • assemblyを使用して、実行可能ファイルを変数としてロードしますAssembly.LoadFrom(string)
  • を使用して、問題のインターフェイスのタイプを取得しますassembly.GetType(string)
  • インターフェースの実装タイプを見つけます。assembly.getType(string)
  • およびを使用して、実装タイプをdynamicオブジェクトにインスタンス化します。type.GetConstructor(Type[])constructor.Invoke(Object[])

この時点で、テストしているインターフェイスを実装していることがわかっているdynamicオブジェクトがあります。loaderのインターフェイスメソッドの1つを呼び出したいobjので、次を実行します。

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;
}

私は(とりわけプログラム出力から)キャストエラーがキャストとともに3行目から発生していると信じる十分な理由がありList<IRange>ます。ただし、トレースは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");
4

2 に答える 2

1

これは素晴らしいアイデアだと思いますが、学生たちの好意にあまりにも傾倒しているようです。

CSxxxx.Interfaces.dll生徒に参照して実装するように要求するアセンブリ(たとえば)を提供できます。そこから実装をロードするのはとても簡単です。

また、すべて合格した場合にC程度になる可能性のある一連のテストを提供することもできます。次に、スイートがすべてをテストします。あなたが少し悪意があり、与えられたテストを延長するために何人かの学生を頼りにすることができれば、他のすべての実装に対してStudentXのテストを実行し、他の実装を破ることに対してボーナスポイントを与えることができます。

于 2012-05-03T20:16:04.637 に答える
1

わかりました。次のコードは、別のアセンブリでメソッドを呼び出す際に機能するようです。

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

これのいくつかを使用してみてください。そのオブジェクトを呼び出して、そのメソッドから結果を取得することができました。

于 2012-05-03T18:27:54.947 に答える