使用 ICorDebugEval 的通用类型 func-eval
Generic type func-eval using ICorDebugEval
我正在使用 MDBG 示例制作托管 .NET 调试器。
MDBG 不支持 属性 吸气剂评估,我正在尝试添加。请考虑以下 class 结构:
public abstract class Base<T>{
public string SomeProp {get;set;}
}
public class A : Base<int>{
}
在某个时间点,我正在创建 A 的实例并在断点处停止以评估它的状态。
在我的调试器监视中 window 我引入了 "this.SomeProp",它应该对该对象执行 get_SomeProp 方法的 func-eval 并且 return 给定的空值案例.
我遇到的第一个问题是 get_SomeProp 是在基础 class 上定义的,所以我不得不 运行 遍历所有 TypeDefs/TypeRefs/TypeSpecs class 层次结构来查找函数。
但是找到后,调用
ICorDebugEval.CallFunction(function.CorFunction, new[] {@object.CorValue});
导致:TypeLoadException:在程序集.
中使用了泛型类型和错误数量的泛型参数
据我所知,这是因为非泛型函数是在泛型 class(基础)中定义的,所以当我评估它时,我还应该指出 class 的泛型参数。
这可以使用
来完成
ICorDebugEval2.CallParameterizedFunction(function.CorFunction,
genericArguments,
functionArguments);
问题是我不知道如何提取 class 通用参数的类型,只有我想评估的函数和我想评估它的实例。
这是我目前正在使用的一些代码:
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;
}
非常感谢suggestion/advice!
此致,
解决方案
感谢@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;
}
您可以在基类型上使用 ICorDebugValue2::GetExactType on the value object representing an instance of A
to get the ICorDebugType for type A
, ICorDebugType::GetBase() to get its base class (Base<int>
) and ICorDebugType::EnumerateTypeParameters 来获取它的类型参数。
我正在使用 MDBG 示例制作托管 .NET 调试器。
MDBG 不支持 属性 吸气剂评估,我正在尝试添加。请考虑以下 class 结构:
public abstract class Base<T>{
public string SomeProp {get;set;}
}
public class A : Base<int>{
}
在某个时间点,我正在创建 A 的实例并在断点处停止以评估它的状态。
在我的调试器监视中 window 我引入了 "this.SomeProp",它应该对该对象执行 get_SomeProp 方法的 func-eval 并且 return 给定的空值案例.
我遇到的第一个问题是 get_SomeProp 是在基础 class 上定义的,所以我不得不 运行 遍历所有 TypeDefs/TypeRefs/TypeSpecs class 层次结构来查找函数。
但是找到后,调用
ICorDebugEval.CallFunction(function.CorFunction, new[] {@object.CorValue});
导致:TypeLoadException:在程序集.
中使用了泛型类型和错误数量的泛型参数据我所知,这是因为非泛型函数是在泛型 class(基础)中定义的,所以当我评估它时,我还应该指出 class 的泛型参数。
这可以使用
来完成 ICorDebugEval2.CallParameterizedFunction(function.CorFunction,
genericArguments,
functionArguments);
问题是我不知道如何提取 class 通用参数的类型,只有我想评估的函数和我想评估它的实例。
这是我目前正在使用的一些代码:
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;
}
非常感谢suggestion/advice!
此致,
解决方案
感谢@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;
}
您可以在基类型上使用 ICorDebugValue2::GetExactType on the value object representing an instance of A
to get the ICorDebugType for type A
, ICorDebugType::GetBase() to get its base class (Base<int>
) and ICorDebugType::EnumerateTypeParameters 来获取它的类型参数。