2016-05-16 15 views
-2

Ich suche nach der Methode, um die Attribute einer bestehenden Methode zu aktualisieren, ohne eine neue Methodendefinition zu erstellen. HierMethodenattribute während JIT aktualisieren?

ist der Code, den ich bisher habe:

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

Wie Sie sehen können, habe ich die Methoden bin fehlt die Funktion Metadaten und ändern in-line abgerufen werden. Die MSDN-Hilfe zu dieser Methode ist sehr dünn und konnte keine Beispiele für die Verwendung von ApplyEditAndContinue finden.

+0

Ich habe stimmen obligatorischer Kommentar für alle (oder zumindest die ersten) Downstimmen ... erspart uns Noobs herauszufinden, warum. – ilen

+1

JITCompilationStarted ist viel zu spät, um Attribute zu ändern, die Attribute könnten überprüft werden, bevor die Methode überhaupt aufgerufen oder JIT'ed wird. Metadaten können nur über den Callback von [ModuleLoadFinished] (https://msdn.microsoft.com/en-us/library/ms230105%28v=vs.110%29.aspx) geändert werden. Warum sollten Sie ApplyEditAndContinue zum Hinzufügen von Attributen anstelle von DefineCustomAttribute verwenden? Was willst du eigentlich erreichen? (und nein, ich bin nicht derjenige, der gewählt hat) –

+0

@BrianReichle, danke für den Heads-up, Grundsätzlich möchte ich reguläre Klassenmethoden zu virtuellen Methoden mutieren lassen, damit sie während Unit Tests verspottet werden können. Das bedeutet, dass ich ein vorhandenes Attribut ändern muss. Grundsätzlich sind nicht-virtuelle Methoden der häufigste Grund für die Schwierigkeit, unseren Legacy-Code zu testen. Und ich würde gerne vermeiden, die Assemblies auf der Festplatte zu modifizieren (zB über [Fody's] (https://github.com/Fody/Fody) [Virtuosity] (https://github.com/Fody/Virtuosity)) – ilen

Antwort

0

Antwort Brians Taking in den Kommentaren:

JITCompilationStarted ist viel zu spät Attribute zu ändern, könnten die Attribute gut kontrolliert werden, bevor das Verfahren überhaupt oder JIT'ed genannt wird. Metadaten können nur über den Callback von ModuleLoadFinished geändert werden.

, die entlang der Linien von (stark reduziert), um Code übersetzt:

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

Diese für spöttische nicht-virtuellen Mitglieder in .NET Eg ermöglichen:

public class Foo { 
    public string Hello() => "test"; 
} 

// ... 
var fake = A.Fake<Foo>(); 
A.CallTo(() => fake.Hello()).Returns("faked"); 
Assert.Equals("faked", fake.Hello());