我正在寻找更新现有方法属性的方法,而无需创建新的方法定义。
以下是我到目前为止的代码:
HRESULT STDMETHODCALLTYPE Weaver::JITCompilationStarted(
FunctionID functionId, BOOL fIsSafeToBlock)
{
HRESULT status = S_OK;
MethodInfo methodInfo = GetMethodInfo(functionId);
if (!IsMdVirtual(methodInfo.Attributes) && !IsMdStatic(methodInfo.Attributes)
&& !IsMdPrivate(methodInfo.Attributes) && !IsMdSpecialName(methodInfo.Attributes))
{
CComPtr<IMetaDataEmit> metaDataEmit;
status = m_profilerInfo3->GetModuleMetaData(methodInfo.Module,
ofRead | ofWrite, IID_IMetaDataEmit, (IUnknown**)&metaDataEmit);
// TODO: get module metadata and update method attributes to: methodInfo.Attributes | mdVirtual
status = metaDataEmit->ApplyEditAndContinue(metaDataEmit /*?*/);
}
return status;
}
如您所见,我缺少检索函数元数据和在线修改的方法。关于此方法的MSDN帮助很薄,找不到ApplyEditAndContinue
的使用示例。
答案 0 :(得分:0)
在评论中采纳Brian的回答:
JITCompilationStarted改变属性为时已晚,在调用方法或JIT之前可以很好地检查属性。元数据只能从ModuleLoadFinished回调中修改。
它转换为(严重缩减)的代码:
HRESULT Weaver::ModuleLoadFinished(ModuleID moduleId, HRESULT hrStatus)
{
HRESULT status = S_OK;
// Filter module
// Enum & filter types in module
// Enum & filter methods in type
DWORD attributes, implFlags; ULONG codeRva;
status = pMetaImport->GetMethodProps(tkMethod, NULL, NULL, NULL, NULL, &attributes, NULL, NULL, &codeRva, &implFlags);
status = pMetaEmit->SetMethodProps(tkMethod, attributes | mdVirtual, codeRva, implFlags);
return status;
}
这将允许在.NET Eg中模拟非虚拟成员:
public class Foo {
public string Hello() => "test";
}
// ...
var fake = A.Fake<Foo>();
A.CallTo(() => fake.Hello()).Returns("faked");
Assert.Equals("faked", fake.Hello());