MDBG サンプルを使用してマネージド .NET デバッガーを作成しています。
MDBG は、私が追加しようとしているプロパティ ゲッターの評価をサポートしていません。次のクラス構造を検討してください。
public abstract class Base<T>{
public string SomeProp {get;set;}
}
public class A : Base<int>{
}
ある時点で、A のインスタンスを作成し、ブレークポイントで停止してその状態を評価しています。
デバッガーのウォッチ ウィンドウで、「this.SomeProp」を導入します。これは、このオブジェクトで get_SomeProp メソッドの関数評価を実行し、特定のケースに対して null 値を返す必要があります。
私が遭遇した最初の問題は、get_SomeProp が基本クラスで定義されていたため、関数を見つけるためにクラス階層内のすべての TypeDefs/TypeRefs/TypeSpecs を実行する必要があったという事実でした。
しかし、それが見つかった後、
ICorDebugEval.CallFunction(function.CorFunction, new[] {@object.CorValue});
結果: TypeLoadException: ジェネリック型が、アセンブリで間違った数のジェネリック引数と共に使用されました。
非ジェネリック関数がジェネリック クラス (ベース) で定義されているために発生することに気付いたので、それを評価するときは、クラスのジェネリック パラメータも示す必要があります。
これは、
ICorDebugEval2.CallParameterizedFunction(function.CorFunction,
genericArguments,
functionArguments);
問題は、評価したい関数とそれを評価したいインスタンスだけを持って、クラスジェネリックパラメータの型を抽出する方法がわからないことです。
ここに私が現在使用しているいくつかのコードがあります:
private MDbgValue EvaluatePropertyGetter(MDbgFrame scope, MDbgValue @object, string propertyName) {
var propertyGetter = $"get_{propertyName}";
var function = ResolveFunctionName(
scope.Function.Module.CorModule.Name,
@object.TypeName,
propertyGetter,
scope.Thread.CorThread.AppDomain);
if (function == null) {
throw new MDbgValueException("Function '" + propertyGetter + "' not found.");
}
var eval = Threads.Active.CorThread.CreateEval();
var typeToken = function.CorFunction.Class.Token;
var type = function.Module.Importer.GetType(typeToken); //checked that type containing function is generic
if (type.IsGenericType) {
//------------->need to get class'es generic param types<------------
var genericType1 = this.ResolveType("System.Object"); // just a stub
eval.CallParameterizedFunction(function.CorFunction, new CorType[] {genericType1}, new[] {@object.CorValue});
}
else {
eval.CallFunction(function.CorFunction, new[] {@object.CorValue});
}
Go().WaitOne();
if (!(StopReason is EvalCompleteStopReason)) {
// we could have received also EvalExceptionStopReason but it's derived from EvalCompleteStopReason
Console.WriteLine("Func-eval not fully completed and debuggee has stopped");
Console.WriteLine("Result of funceval won't be printed when finished.");
}
else {
eval = (StopReason as EvalCompleteStopReason).Eval;
Debug.Assert(eval != null);
var cv = eval.Result;
if (cv != null) {
var mv = new MDbgValue(this, cv);
return mv;
}
}
return null;
}
どんな提案/アドバイスも大歓迎です!
よろしく、
解決
@Brian Reichleの優れた回答のおかげで、私はこの解決策を思いつきました:
if (type.IsGenericType) {
//getting Type's Generic parameters
var typeParams = GetGenericArgs(@object.CorValue.ExactType, function.CorFunction.Class.Token);
eval.CallParameterizedFunction(function.CorFunction, typeParams.ToArray(), new[] {@object.CorValue});
}
そして関数自体:
private List<CorType> GetGenericArgs(CorType corType, int classTk) {
if (corType == null)
return null;
List<CorType> list = new List<CorType>();
var param =corType.TypeParameters;
var args = GetGenericArgs(corType.Base, classTk);
if (classTk == corType.Class.Token) {
list.AddRange(param.Cast<CorType>());
}
if (args != null) {
list.AddRange(args);}
return list;
}