Como a estrutura de isolamento de Moles é implementada?

Moles é uma estrutura de isolamento criada pela Microsoft. Um recurso interessante do Moles é que ele pode “simular” methods estáticos / não virtuais e classs seladas (o que não é possível com frameworks como o Moq). Abaixo está a rápida demonstração do que as Moles podem fazer:

Assert.AreNotEqual(new DateTime(2012, 1, 1), DateTime.Now); // MDateTime is part of Moles; the below will "override" DateTime.Now's behavior MDateTime.NowGet = () => new DateTime(2012, 1, 1); Assert.AreEqual(new DateTime(2012, 1, 1), DateTime.Now); 

Parece que Moles é capaz de modificar o corpo CIL de coisas como DateTime.Now em tempo de execução. Como o Moles não é open-source, estou curioso para saber qual mecanismo o Moles usa para modificar o CIL dos methods em tempo de execução. Alguém pode lançar alguma luz?

Moles implementa um profiler CLR (em particular, a interface ICorProfilerCallback ) que permite rewrite corpos de método MSIL antes que eles sejam compilados em código de assembly pelo tempo de execução do .NET. Isso é feito em particular por meio do retorno de chamada JitCompileStarted .

Em cada método, o Moles apresenta um desvio semelhante a este:

 static struct DateTime { static DateTime Now { get { Func d = __Detours.GetDelegate( null, // this point null in static methods methodof(here) // current method token ); if(d != null) return d(); ... // original body } } } 

Quando você configura uma mole, seu delegado é armazenado no dictionary __Detours subjacente, que é consultado quando o método é executado.

Isso está funcionando como wrapper para qualquer assembly desejado, por exemplo mscorlib (este exemplo baseia-se no Moles Assembly Wrapper do mscorlib ). Isso dando a você poder para replace qualquer método .NET pelo delegado escrito pelo codificador .

Isso não está funcionando automaticamente. Você deve primeiro criar antes que este começo funcione, arquivo de configuração XML Moles com lista de Assemblies para “Wrapper” e por este código Moles geram uma Referências deste assemblies a partir do arquivo de configuração. E você deve neste arquivo adicionar using namespace System.Moles e antes da function [HostType("Moles")]