ã¯ããã«
ãã®èšäºã§ã¯ãæ¢åã®.NETã¢ã»ã³ããªã«ã³ãŒããè¿œå ããæ¹æ³ãšãã¢ã¹ãã¯ãæåããã°ã©ãã³ã°ãšã®é¢ä¿ã«ã€ããŠèª¬æããŸãã ã³ãŒãã¯ã¢ã€ãã¢ãäŒããããã®æè¯ã®æ¹æ³ã§ãããšç§ã¯ä¿¡ããŠããã®ã§ãèšäºã«ã¯å®éã®äŸãæ·»ä»ãããŸãã
å€ãã®.NETéçºè
ã¯ãReflectionã䜿çšããŠå¥ã®ã¢ã»ã³ããªã®ãªããžã§ã¯ãã«ã¢ã¯ã»ã¹ã§ããããšãç¥ã£ãŠããŸãã System.Reflectionã®åã䜿çšããŠãã¢ã»ã³ããªå
ã®å€ãã®.NETãªããžã§ã¯ãã«ã¢ã¯ã»ã¹ãããããã®ã¡ã¿ããŒã¿ã衚瀺ããã¢ã¯ã»ã¹ã«å¶éãããŠãããªããžã§ã¯ãïŒå¥ã®ã¯ã©ã¹ã®ãã©ã€ããŒãã¡ãœãããªã©ïŒã䜿çšããããšãã§ããŸãã ãã ããReflectionã®äœ¿çšã«ã¯å¶éãããããã®äž»ãªçç±ã¯ãReflectionã䜿çšããŠäœæ¥ããããŒã¿ããŸã ã³ãŒããšèŠãªãããããšã§ãã ãããã£ãŠãããšãã°ãReflectionãé©çšããããšããŠããã¢ã»ã³ããªããããçŠæ¢ããŠããå ŽåãCodeAccessSecurityäŸå€ãååŸã§ããŸãã åãçç±ã§ãåå°ã¯ããªãé
ãã§ãã ãã ãããã®èšäºã§æãéèŠãªããšã¯ãæšæºã®Reflectionã§ã¯æ¢åã®ã¢ã»ã³ããªãå€æŽããããšã¯ã§ãããæ°ããã¢ã»ã³ããªã®ã¿ãçæããŠä¿åããããšã§ãã
ã¢ãã»ã·ã«
å®å
šã«ç°ãªãã¢ãããŒãããç¡æã®ãªãŒãã³ãœãŒã¹ã©ã€ãã©ãªMono.Cecilã«ãã£ãŠæäŸãããŠããŸãã Mono.Cecilã¢ãããŒããšReflectionã¢ãããŒãã®äž»ãªéãã¯ããã®ã©ã€ãã©ãªããã€ãã¹ããªãŒã ãšããŠNETã¢ã»ã³ããªãšé£æºããããšã§ãã Mono.Cecilã¯ãã¢ã»ã³ããªãèªã¿èŸŒããšãã«ãPEããããŒãCLRããããŒãã¯ã©ã¹ããã³ã¡ãœããã®MSILã³ãŒããªã©ã解æããŸãã ã¢ã»ã³ããªãè¡šããã€ãã¹ããªãŒã ãçŽæ¥æäœããŸãã ãããã£ãŠããã®ã©ã€ãã©ãªã䜿çšããŠãæ¢åã®ã¢ã»ã³ããªãïŒå¢çå
ã§ïŒå¿
èŠã«å¿ããŠå€æŽã§ããŸãã
Mono.Cecilã¯
ãã¡ãããããŠã³ããŒãã§ããŸãã
ããã«ãå³å¯ãªååã§çœ²åããããµãŒãããŒãã£ã®ã¢ã»ã³ããªãå€æŽãããšã眲åããªã»ããããããã®åŸã®çµæããã¹ãŠçããããšã«æ³šæããŠãã ããã å€æŽåŸãã¢ã»ã³ããªã«å眲åããããšãã§ããŸãïŒåãããŒã䜿çšããå ŽåããŸãã¯å¥ã®ããŒã䜿çšãã-ããšãã°ãã¢ã»ã³ããªãGACã«é
眮ããå¿
èŠãããå ŽåïŒã
å°ããªäŸ
Mono.Cecilã®æ©èœã䜿çšããäŸãèŠãŠãã ããã ãœãŒã¹ããã°ã©ã ã®ãªãã³ã³ãœãŒã«ã¢ããªã±ãŒã·ã§ã³ã®ãµãŒãããŒãã£ã¢ã»ã³ããªããããããã«ã¿ã€ãProgramããããšããŸãã ãœãŒã¹ã³ãŒãã«ã¯ã¢ã¯ã»ã¹ã§ããŸããããåã¡ãœãããåŒã³åºããããšãã«ãã®ã¢ããªã±ãŒã·ã§ã³ãã³ã³ãœãŒã«ã«ã¡ãã»ãŒãžãåºåããããã«ããŸãã ãããè¡ãã«ã¯ãç¬èªã®ã³ã³ãœãŒã«ã¢ããªã±ãŒã·ã§ã³ãäœæããŸãã èµ·åæã®åŒæ°ãšããŠãã¿ãŒã²ããã¢ããªã±ãŒã·ã§ã³ã«ãã¹ãæž¡ããŸãã
using Mono.Cecil; using Mono.Cecil.Cil; class Program { static void Main(string[] args) { if (args.Length == 0) return; string assemblyPath = args[0]; // Mono.Cecil var assembly = AssemblyDefinition.ReadAssembly(assemblyPath); // Console.WriteLine, Reflection var writeLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }); // , Reflection, Mono.Cecil var writeLineRef = assembly.MainModule.Import(writeLineMethod); foreach (var typeDef in assembly.MainModule.Types) { foreach (var method in typeDef.Methods) { // // "Inject!" method.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Ldstr, "Inject!")); // Console.WriteLine, - "Injected". method.Body.Instructions.Insert(1, Instruction.Create(OpCodes.Call, writeLineRef)); } } assembly.Write(assemblyPath); } }
ãµãŒãããŒãã£ã¢ã»ã³ããªãžã®ãã¹ãã³ã³ãœãŒã«ã¢ããªã±ãŒã·ã§ã³ã«è»¢éããå ŽåãåILã¡ãœããã®éå§æã«ã³ãŒããInjectïŒããã³ã³ãœãŒã«ã«è¿œå ãããå€æŽãããã¢ã»ã³ããªãä¿åãããŸãã å€æŽãããã¢ã»ã³ããªãéå§ãããšãåã¡ãœããã¯ãInjectïŒãã³ã³ãœãŒã«ã«æžã蟌ã¿ãŸãã
äžèšã®ã³ãŒãã詳ããèŠãŠã¿ãŸãããã ãåãã®ãšãããNETã¯å€ãã®ããã°ã©ãã³ã°èšèªããµããŒãããŠããŸãã ããã¯ãããã°ã©ãã³ã°èšèªã®ã³ãŒãã¯ãã¹ãŠãäžéèšèªã§ããCILïŒCommon Intermediate LanguageïŒã«ã³ã³ãã€ã«ãããããã§ãã ãªããã®éã«ïŒ ãªããªããCILã³ãŒãã¯å¯Ÿå¿ããããã»ããµãŒã®åœä»€ã«å€æãããããã§ãã ãããã£ãŠãã©ã®èšèªã®ã³ãŒããã»ãŒåãCILã³ãŒãã«ã³ã³ãã€ã«ãããŸããããã«ãããããšãã°ãCïŒãããžã§ã¯ãã®VBäžã®ã¢ã»ã³ããªã䜿çšã§ããŸãã
ãããã£ãŠãåã¢ã»ã³ããªã¯ãçžå¯Ÿçã«èšãã°ãã¡ã¿ããŒã¿ã®ã»ããïŒããšãã°ãReflectionã䜿çšïŒãšCILã®åœä»€ã®ã»ããã§ãã
ããã¯ãã®èšäºã®ãããã¯ã§ã¯ãªãã®ã§ãCILã®èª¬æã«ã¯è§ŠããŸããã å°æ¥ã«ãšã£ãŠéèŠãªãã®ãã€ãŸãCILåœä»€ã®äžéšã®æ©èœã«éå®ããŸãã ã¡ã¿ããŒã¿ã®ãã¬ãŒã³ããŒã·ã§ã³ã«é¢ããæ
å ±ããã€ã³ã¿ãŒãããäžã®ãã®ä»ã®æ瀺ããã€ã§ãèŠã€ããããšãã§ããŸãã
éå§ããã«ã¯ãäžèšã®äŸã®ã³ãŒãéšåãæ€èšããŠãã ããã
method.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Ldstr, "Inject!")); method.Body.Instructions.Insert(1, Instruction.Create(OpCodes.Call, writeLineRef));
ãã®ã³ãŒãã§ã¯ãäœããã®ã¡ãœããã®äžé£ã®CILåœä»€ã«ã¢ã¯ã»ã¹ããŠãç¬èªã®CILåœä»€ãè¿œå ããŸããã CILåœä»€ã»ããã¯æ¬¡ã®ãšããã§ãã CILãçŽæ¥äœ¿çšããå Žåãã¹ã¿ãã¯ã¯éèŠã§ãã ã¹ã¿ãã¯ã«ããŒã¿ãå
¥ããŠãããããååŸããããšãã§ããŸãïŒã¹ã¿ãã¯ã®ååã«åŸã£ãŠïŒã äžèšã®äŸã§ã¯ãLdstråœä»€ã䜿çšããŠããInjectïŒããšããè¡ãã¹ã¿ãã¯ã«ããã·ã¥ããŸãã 次ã«ãSystem.Console.WriteLineãåŒã³åºããŸãã ã¡ãœããåŒã³åºãã¯ãã¹ãŠãã¹ã¿ãã¯ã«ã¢ã¯ã»ã¹ããŠå¿
èŠãªåŒæ°ãååŸããŸãã ãã®å ŽåãSystem.Console.WriteLineã«ã¯æåååã®åŒæ°ãå¿
èŠã§ããããã¹ã¿ãã¯ã«ããŒãããŸããã callã¹ããŒãã¡ã³ãã¯åŒæ°ãæåŸããããŒããããããéåžžã®æ¹æ³ã§åŒæ°å€ãã¹ã¿ãã¯ã«ããŒãããå¿
èŠããããŸãã ãããã£ãŠããã®åœä»€ã¯ããInjectïŒãã«çããæåååã®ãã©ã¡ãŒã¿ãŒã䜿çšããŠãSystem.Console.WriteLineã¡ãœããã«å¶åŸ¡ã転éããŸãã ãã®äžé£ã®æ瀺ã¯ã次ã®ãã®ãšåçã§ãã
System.Console.WriteLine("Injected!");
Mono.Cecilã¯ã¢ã»ã³ããªãäžé£ã®åœä»€ïŒãã€ãïŒãšããŠèªèãããããå¶éãªãã³ã³ãã³ããå€æŽã§ããŸãã CILã³ãŒããè¿œå ããåŸããããïŒãã€ãã®ã»ãããšããŠïŒä¿åããå€æŽãããã¢ã»ã³ããªãååŸããŸãã
ã¢ã¹ãã¯ãæåã®ã¢ãããŒããå®è£
ããããã®ã³ãŒãçæã®å®éã®ã¢ããªã±ãŒã·ã§ã³
äžèšã®ã¢ãããŒããç¬èªã®ã¢ã»ã³ããªã«é©çšããããšãæ€èšããŠãã ããã ã¡ãœãããéå§ãŸãã¯çµäºãããšãã«ã³ãŒããå®è¡ããã¡ãœãããŸãã¯ãã®ã³ã³ããã¹ããèšè¿°ããããŒã¿ã«ã¢ã¯ã»ã¹ãããå ŽåããããããŸãã æãåçŽãªäŸã¯ãã¬ãŒã§ãã åã¡ãœããã®å
¥åãšåºåããã°ã«èšé²ããå Žåãåã¡ãœããã®æåãšæåŸã«å調ãªã³ãŒããæžãã®ã¯éåžžã«é¢åã§ãã ãŸããç§ã®æèŠã§ã¯ãããã¯ããæ±ãã³ãŒãã§ãã ããã«ãã¹ã¿ãã¯äžã®ã¡ãœããã®ãã©ã¡ãŒã¿ãŒã«èªåçã«ã¢ã¯ã»ã¹ããããšã¯ã§ããŸããããŸããå
¥åã§ãã©ã¡ãŒã¿ãŒã®ç¶æ
ãèšé²ããå Žåã¯ãæåã§ãããè¡ãå¿
èŠããããŸãã 2çªç®ã®æ¢ç¥ã®åé¡ã¯ãåããããã£ã«æåã§å²ãåœãŠãå¿
èŠãããINotifyPropertyChangedã®å®è£
ã§ãã
å¥ã®ã¢ãããŒããæ€èšããŠãã ããã ãã¹ãããã«ã¯ãæ°ããã³ã³ãœãŒã«ã¢ããªã±ãŒã·ã§ã³ãäœæããŸãã ã¯ã©ã¹ãè¿œå ããŸãã
[AttributeUsage(AttributeTargets.Method)] public class MethodInterceptionAttribute : Attribute { public virtual void OnEnter(System.Reflection.MethodBase method, Dictionary<string, object> parameters) { } public virtual void OnExit() { } }
ãŠãŒã¶ãŒã¯ãã®ã¯ã©ã¹ãç¶æ¿ããOnEnterã¡ãœããããªãŒããŒã©ã€ãããç¶æ¿ãããå±æ§ãä»»æã®ã¡ãœããã«é©çšã§ããŸãã ç§ãã¡ã®ç®æšã¯ã次ã®æ©äŒãå®çŸããããšã§ãïŒMethodInterceptionAttributeã¿ã€ãã®å±æ§ã§ããŒã¯ãããã¡ãœãããå
¥åãããšããOnEnterãåŒã³åºããã¡ãœãããžã®åç
§ãšããã®ã¡ãœããã®ãã©ã¡ãŒã¿ãŒã»ããã<parameter nameïŒvalue>ã®åœ¢åŒã§æž¡ããŸãã
å®éšã®ããã«ã2ã€ã®ã³ã³ãœãŒã«ã¢ããªã±ãŒã·ã§ã³ãäœæããŸãã æåã®ãã®ã«ã¯ãå±æ§å®çŸ©ãšããµãŒãããŒãã£ã¢ããªã±ãŒã·ã§ã³ã«ã³ãŒããæ¿å
¥ããããã«å¿
èŠãªãã¹ãŠã®ã¡ãœãããå«ãŸããŸãã 2çªç®ã®ã¢ããªã±ãŒã·ã§ã³ã¯ãã¹ãã«ãªããŸãã æåã«ããã¹ãã¢ããªã±ãŒã·ã§ã³ã®çãã³ãŒããæ€èšããŸãã
class Program { static void Main(string[] args) { MethodToChange("Test"); } [TestMethodInterception()] public static void MethodToChange(string text) { Console.ReadLine(); } } public class TestMethodInterceptionAttribute : MethodInterceptionAttribute { public override void OnEnter(System.Reflection.MethodBase method, Dictionary<string, object> parameters) { Console.WriteLine("Entering method " + method.Name + "..." + Environment.NewLine); foreach (string paramName in parameters.Keys) { Console.WriteLine("Parameter " + paramName + " has value " + parameters[paramName] + Environment.NewLine); } } }
ããã¯ãTestã«çããtextãã©ã¡ãŒã¿ãŒã§MethodToChangeã¡ãœãããåŒã³åºãåçŽãªã³ã³ãœãŒã«ã¢ããªã±ãŒã·ã§ã³ã§ãã ãã®ã¡ãœããã¯ãMethodInterceptionAttributeããç¶æ¿ãããTestMethodInterceptionAttributeå±æ§ã§ããŒã¯ãããŸãã OnEnterãåå®çŸ©ããããã®å±æ§ã§ããŒã¯ãããã¡ãœããã«é¢ããæ
å ±ãã³ã³ãœãŒã«ã«è¡šç€ºãããŸãã ååŠçãè¡ããªããšããã®ã¢ããªã±ãŒã·ã§ã³ã¯èµ·åæã«Console.ReadLineãåŒã³åºããŠçµäºããŸãã
ã¡ã€ã³ã¢ããªã±ãŒã·ã§ã³ïŒã³ã³ãœãŒã«ãïŒã®æ€èšãç¶ããŸãã MSILã³ãŒãã®äŸã瀺ãããããªãéçºãæ¯æŽããããã«ã次ã®ãã«ããŒã¡ãœãããèšè¿°ããŸãã
static void DumpAssembly(string path, string methodName) { System.IO.File.AppendAllText("dump.txt", "Dump started... " + Environment.NewLine); var assembly = AssemblyDefinition.ReadAssembly(path); foreach (var typeDef in assembly.MainModule.Types) { foreach (var method in typeDef.Methods) { if (String.IsNullOrEmpty(methodName) || method.Name == methodName) { System.IO.File.AppendAllText("dump.txt", "Method: " + method.ToString()); System.IO.File.AppendAllText("dump.txt", Environment.NewLine); foreach (var instruction in method.Body.Instructions) { System.IO.File.AppendAllText("dump.txt", instruction.ToString() + Environment.NewLine); } } } } }
ãã®ã¡ãœããã¯ããã«ãã¡ãœããïŒãŸãã¯ãã¹ãŠïŒããæ¢åã®MSILã³ãŒããèªã¿åããdump.txtã«æžã蟌ã¿ãŸãã ããã¯ã©ã®ããã«åœ¹ç«ã¡ãŸããïŒ ãµãŒãããŒãã£ã¢ã»ã³ããªã«è¿œå ããç¹å®ã®ã³ãŒãã¯ããã£ãŠãããããã¹ãŠã®MSILã³ãŒããæåããèšè¿°ããããªãå ŽåãèããŸãã 次ã«ããã®ã³ãŒããCïŒã§ããã€ãã®ã¡ãœããã«èšè¿°ãããã³ãããŸãã ãã®åŸãMono.Cecilã䜿çšããŠMSILãèšè¿°ããæ¹ãã¯ããã«ç°¡åã«ãªããŸããæ¢ã«ã©ã®ããã«èŠãããã®æ¢è£œã®ãµã³ãã«ããããŸãïŒãã¡ãããä»ã®ãã䟿å©ãªã¡ãœããã䜿çšããŠMSILã¢ã»ã³ããªã³ãŒãã衚瀺ã§ããŸãïŒã
åã¡ãœããã®æåã«äœãååŸããããïŒCïŒã®åœ¢åŒã§ïŒãæ€èšããŠãã ããã
var currentMethod = System.Reflection.MethodBase.GetCurrentMethod(); var attribute = (MethodInterceptionAttribute)Attribute.GetCustomAttribute(currentMethod, typeof(MethodInterceptionAttribute)); Dictionary<string, object> parameters = new Dictionary<string, object>();
ãã®MSILã³ãŒãã®ãã³ãã®äžéšïŒ
IL_0000: nop
IL_0001: call System.Reflection.MethodBase System.Reflection.MethodBase::GetCurrentMethod()
IL_0006: ldtoken EmitExperiments.MethodInterceptionAttribute
IL_000b: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
IL_0010: call System.Attribute System.Attribute::GetCustomAttribute(System.Reflection.MemberInfo,System.Type)
IL_0015: castclass EmitExperiments.MethodInterceptionAttribute
IL_001a: stloc V_1
IL_001e: ldloc V_1
IL_0022: callvirt System.Void EmitExperiments.MethodInterceptionAttribute::OnEnter()
...
次ã«ãInjectToAssemblyã¡ãœããã®å®å
šãªã³ãŒãïŒè©³çŽ°ãªã³ã¡ã³ãä»ãïŒãæå®ããŸããããã«ãããæå®ããã¢ã»ã³ããªã®MethodInterceptionAttributeãæã€ãã¹ãŠã®ã¡ãœããã«å¿
èŠãªã³ãŒããè¿œå ãããŸãã
static void InjectToAssembly(string path) { var assembly = AssemblyDefinition.ReadAssembly(path); // GetCurrentMethod() var getCurrentMethodRef = assembly.MainModule.Import(typeof(System.Reflection.MethodBase).GetMethod("GetCurrentMethod")); // Attribute.GetCustomAttribute() var getCustomAttributeRef = assembly.MainModule.Import(typeof(System.Attribute).GetMethod("GetCustomAttribute", new Type[] { typeof(System.Reflection.MethodInfo), typeof(Type) })); // Type.GetTypeFromHandle() - typeof() var getTypeFromHandleRef = assembly.MainModule.Import(typeof(Type).GetMethod("GetTypeFromHandle")); // MethodBase var methodBaseRef = assembly.MainModule.Import(typeof(System.Reflection.MethodBase)); // MethodInterceptionAttribute var interceptionAttributeRef = assembly.MainModule.Import(typeof(MethodInterceptionAttribute)); // MethodInterceptionAttribute.OnEnter var interceptionAttributeOnEnter = assembly.MainModule.Import(typeof(MethodInterceptionAttribute).GetMethod("OnEnter")); // Dictionary<string,object> var dictionaryType = Type.GetType("System.Collections.Generic.Dictionary`2[System.String,System.Object]"); var dictStringObjectRef = assembly.MainModule.Import(dictionaryType); var dictConstructorRef = assembly.MainModule.Import(dictionaryType.GetConstructor(Type.EmptyTypes)); var dictMethodAddRef = assembly.MainModule.Import(dictionaryType.GetMethod("Add")); foreach (var typeDef in assembly.MainModule.Types) { foreach (var method in typeDef.Methods.Where(m => m.CustomAttributes.Where( attr => attr.AttributeType.Resolve().BaseType.Name == "MethodInterceptionAttribute").FirstOrDefault() != null)) { var ilProc = method.Body.GetILProcessor(); // InitLocals true, false ( ) // - IL . method.Body.InitLocals = true; // attribute, currentMethod parameters var attributeVariable = new VariableDefinition(interceptionAttributeRef); var currentMethodVar = new VariableDefinition(methodBaseRef); var parametersVariable = new VariableDefinition(dictStringObjectRef); ilProc.Body.Variables.Add(attributeVariable); ilProc.Body.Variables.Add(currentMethodVar); ilProc.Body.Variables.Add(parametersVariable); Instruction firstInstruction = ilProc.Body.Instructions[0]; ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Nop)); // ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Call, getCurrentMethodRef)); // currentMethodVar ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Stloc, currentMethodVar)); // ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Ldloc, currentMethodVar)); // MethodInterceptionAttribute ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Ldtoken, interceptionAttributeRef)); // GetTypeFromHandle ( typeof()) - typeof(MethodInterceptionAttribute) ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Call, getTypeFromHandleRef)); // MethodInterceptionAttribute. Attribute.GetCustomAttribute ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Call, getCustomAttributeRef)); // MethodInterceptionAttribute ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Castclass, interceptionAttributeRef)); // attributeVariable ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Stloc, attributeVariable)); // Dictionary<stirng, object> ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Newobj, dictConstructorRef)); // parametersVariable ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Stloc, parametersVariable)); foreach (var argument in method.Parameters) { // // Dictionary<string,object> ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Ldloc, parametersVariable)); // ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Ldstr, argument.Name)); // ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Ldarg, argument)); // Dictionary.Add(string key, object value) ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Call, dictMethodAddRef)); } // , OnEnter ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Ldloc, attributeVariable)); ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Ldloc, currentMethodVar)); ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Ldloc, parametersVariable)); // OnEnter. , OnEnter ilProc.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Callvirt, interceptionAttributeOnEnter)); } } assembly.Write(path); } }
ã³ã³ãœãŒã«ã¢ããªã±ãŒã·ã§ã³ã®Mainã¡ãœãããå¿ããªãã§ãã ããã
static void Main(string[] args) { if (args.Length > 0) { string mode = args[0]; string path = args[1]; if (mode == "-dump") { string methodName = args.Length > 2 ? args[2] : String.Empty; DumpAssembly(path, methodName); } else if (mode == "-inject") { InjectToAssembly(args[1]); } } }
ã§ããïŒ ããã§ã-injectãã©ã¡ãŒã¿ãŒã䜿çšããŠã¡ã€ã³ã¢ããªã±ãŒã·ã§ã³ãå®è¡ãããã¹ãã¢ããªã±ãŒã·ã§ã³ãžã®ãã¹ãæž¡ããšãMethodToChangeã¡ãœããã®ã³ãŒãã¯æ¬¡ã®ããã«å€æŽãããŸãïŒReflectorã䜿çšããŠååŸïŒã
[TestMethodInterception] public static void MethodToChange(string text) { MethodBase currentMethod = MethodBase.GetCurrentMethod(); MethodInterceptionAttribute customAttribute = (MethodInterceptionAttribute) Attribute.GetCustomAttribute(currentMethod, typeof(MethodInterceptionAttribute)); Dictionary<string, object> parameters = new Dictionary<string, object>(); parameters.Add("text", text); customAttribute.OnEnter(currentMethod, parameters); Console.ReadLine(); }
å¿
èŠã§ããã ããã§ãTestMethodInterceptionã§ããŒã¯ãããåã¡ãœãããã€ã³ã¿ãŒã»ãããããå€ãã®ç¹°ãè¿ãã³ãŒããèšè¿°ããã«ååŒã³åºããåŠçãããŸãã ããã»ã¹ãèªååããã«ã¯ãVSã§ãã«ãåŸã€ãã³ãã䜿çšããŸããããã«ããããããžã§ã¯ãã®æ§ç¯ãæåããåŸãå®æããã¢ã»ã³ããªãèªåçã«åŠçããå±æ§ã«åºã¥ããŠã³ãŒããå®è£
ã§ããŸãã ã¯ã©ã¹ãŸãã¯ã¢ã»ã³ããªã¬ãã«ã®å±æ§ãäœæããŠãã³ãŒãããã¹ãŠã®ã¯ã©ã¹ãŸãã¯ã¢ã»ã³ããªã¡ãœããã«äžåºŠã«åã蟌ãããšãã§ããŸãã
ãã®ã¢ãããŒãã¯ã.NETã§ã¢ã¹ãã¯ãæåããã°ã©ãã³ã°ææ³ã䜿çšããäŸã§ãã ç§ã¯AOPãäœã§ãããã«ã€ããŠã¯è§ŠããŸãããäžè¬çã«ã¯ã
Wikipediaã§ãã€ã§ãèªãããšãã§ããŸãã .NETã§AOPã®ååã䜿çšã§ããæãæåãªã©ã€ãã©ãªã¯
PostSharpã§ã ãããã«ãããã¢ã»ã³ããªã«ã³ãŒããæ¿å
¥ããŠåæ§ã®æ©èœãå®è£
ããããã«å¿ããŠãã®èšäºãæžãå¯èœæ§ãç 究ããããšã«ãªããŸããã
AOPã䜿çšãããšãäž»ã«ã»ãšãã©ã®ã³ãŒããã¢ã¹ãã¯ãã«åºã¥ããŠèªåçã«çæããããããã¯ãªãŒã³ã§ä¿å®ã容æãªã³ãŒããäœæã§ããŸãã
ãã®èšäºã§ã¯ãMono.Cecilã䜿çšããŠæ¢åã®NETã¢ã»ã³ããªã«ã³ãŒããè¿œå ããæ¹æ³ãããã³Netã§AOPã®ååãå®è£
ããæ¹æ³ã詳现ã«èª¬æããããšããŸããã