{"id":576,"date":"2010-05-19T22:53:32","date_gmt":"2010-05-19T20:53:32","guid":{"rendered":"http:\/\/dev.bratched.fr\/fr\/methodes-dynamiques-classe-dynamicmethod-en-net\/"},"modified":"2010-05-19T22:53:32","modified_gmt":"2010-05-19T20:53:32","slug":"methodes-dynamiques-classe-dynamicmethod-en-net","status":"publish","type":"post","link":"https:\/\/bratched.com\/fr\/2010\/05\/19\/methodes-dynamiques-classe-dynamicmethod-en-net\/","title":{"rendered":"M\u00e9thodes dynamiques (classe DynamicMethod) en .NET"},"content":{"rendered":"<p>Utiliser la r\u00e9flexion pour invoquer des m\u00e9thodes non connues \u00e0 la compilation peut \u00eatre probl\u00e9matique en terme de performances dans des applications critiques. L\u2019ex\u00e9cution de ces m\u00e9thodes est environ 2,5 \u00e0 3 fois plus lente qu\u2019un appel directe.<br \/>\nVoici un exemple :<\/p>\n<div id=\"scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:0c8078d0-64de-4fc4-b313-374421865196\" class=\"wlWriterSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<pre>    class Program\n    {\n        [DllImport(\"kernel32.dll\")]\n        static extern void QueryPerformanceCounter(ref long ticks);\n\n        static PropertyInfo _intProp = typeof(Foo).GetProperty(\"IntProp\", BindingFlags.Public | BindingFlags.Instance);\n\n        static void Main(string[] args)\n        {\n            Foo foo = new Foo { IntProp = 10 };\n            const int COUNT = 1;\n            Console.WriteLine(Measure(() =&gt; ReadPropertyWithReflection(foo), COUNT));\n            Console.WriteLine(Measure(() =&gt; ReadPropertyDirectly(foo), COUNT));\n        }\n\n        static void ReadPropertyWithReflection(Foo foo)\n        {\n            int intProp = (int)_intProp.GetValue(foo, null);\n        }\n\n        static void ReadPropertyDirectly(Foo foo)\n        {\n            int intProp = foo.IntProp;\n        }\n\n        static long Measure(Action action, int count)\n        {\n            long startTicks = 0;\n            QueryPerformanceCounter(ref startTicks);\n            for (int i = 0; i &lt; count; i++)\n            {\n                action();\n            }\n            long endTicks = 0;\n            QueryPerformanceCounter(ref endTicks);\n            return endTicks - startTicks;\n        }\n\n        class Foo\n        {\n            public int IntProp { get; set; }\n        }\n    }<\/pre>\n<\/div>\n<p>Et voici les r\u00e9sultats :<\/p>\n<table border=\"1\" width=\"400\" cellspacing=\"0\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"200\"><strong>Type d\u2019acc\u00e8s<\/strong><\/td>\n<td valign=\"top\" width=\"198\"><strong>unit\u00e9s CPU <\/strong><\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"200\">Invocation par acc\u00e8s directe<\/td>\n<td valign=\"top\" width=\"198\">796<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"200\">Invocation par R\u00e9flexion<\/td>\n<td valign=\"top\" width=\"198\">1986<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Ainsi, l\u2019utilisation de la r\u00e9flexion pour lire une propri\u00e9t\u00e9 est 2,5 fois plus lente que l\u2019acc\u00e8s directe \u00e0 cette propri\u00e9t\u00e9.<\/p>\n<p>Les m\u00e9thodes dynamiques peuvent \u00eatre utilis\u00e9es\u00a0pour g\u00e9n\u00e9rer et ex\u00e9cuter une m\u00e9thode \u00e0 l\u2019ex\u00e9cution sans devoir d\u00e9clarer une assemblie dynamique et un type dynamique qui contiendront la m\u00e9thode. Elles repr\u00e9sentent un moyen plus efficace pour g\u00e9n\u00e9rer et ex\u00e9cuter ce type de code.<\/p>\n<p><!--more--><br \/>\nVoici un exemple d\u2019utilisation de la classe de m\u00e9thode dynamique (DynamicMethod) pour g\u00e9n\u00e9rer un acc\u00e8s en lecture \u00e0 la propri\u00e9t\u00e9.<\/p>\n<div id=\"scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:8054fa8e-357e-4415-ac4a-e989a28e5720\" class=\"wlWriterSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<pre>    static Func&lt;Arg0, TReturn&gt; EmitGetter&lt;Arg0, TReturn&gt;(PropertyInfo propertyInfo)\n    {\n        MethodInfo mi = propertyInfo.GetGetMethod();\n        DynamicMethod dm = new DynamicMethod(\n            \"_get\",\n            typeof(TReturn),\n            new Type[] { typeof(Arg0) },\n            propertyInfo.DeclaringType);\n\n        ILGenerator il = dm.GetILGenerator();\n        il.Emit(OpCodes.Ldarg_0);\n        il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);\n        il.EmitCall(OpCodes.Callvirt, mi, null);\n        il.Emit(OpCodes.Ret);\n\n        return (Func&lt;Arg0, TReturn&gt;)dm.CreateDelegate(typeof(Func&lt;Arg0, TReturn&gt;));\n    }\n<\/pre>\n<\/div>\n<p>Utilisons maintenant cette m\u00e9thode pour d\u00e9finir un acc\u00e8s en lecture\u00a0\u00e0 PropertyInfo en ex\u00e9cution et retourner le d\u00e9l\u00e9gu\u00e9.<\/p>\n<div id=\"scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:a9783508-2fd4-4d82-93a9-eee85e4076ac\" class=\"wlWriterSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<pre>    Func&lt;Foo, int&gt; getter = EmitGetter&lt;Foo, int&gt;(_intProp);\n    Console.WriteLine(Measure(() =&gt; getter(foo), COUNT));\n<\/pre>\n<\/div>\n<p>Et voici les r\u00e9sultats obtenus avec les 3 type d\u2019acc\u00e8s diff\u00e9rents pour lire la valeur de la propri\u00e9t\u00e9 :<\/p>\n<table border=\"1\" width=\"400\" cellspacing=\"0\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"202\"><strong>Type d\u2019acc\u00e8s<\/strong><\/td>\n<td valign=\"top\" width=\"196\"><strong>unit\u00e9s CPU <\/strong><\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"202\">Invocation par acc\u00e8s directe<\/td>\n<td valign=\"top\" width=\"196\">796<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"202\">Invocation\u00a0avec Dynamic method<\/td>\n<td valign=\"top\" width=\"196\"><strong>1190<\/strong><\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"202\">Invocation par R\u00e9flexion<\/td>\n<td valign=\"top\" width=\"196\">1986<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"clearfix\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Utiliser la r\u00e9flexion pour invoquer des m\u00e9thodes non connues \u00e0 la compilation peut \u00eatre probl\u00e9matique en terme de performances dans des applications critiques. L\u2019ex\u00e9cution de ces m\u00e9thodes est environ 2,5 \u00e0 3 fois plus lente qu\u2019un appel directe. Voici un exemple : class Program { [DllImport(\u00ab\u00a0kernel32.dll\u00a0\u00bb)] static extern void QueryPerformanceCounter(ref long ticks); static PropertyInfo _intProp [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[34],"tags":[18,46,47,24],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/posts\/576"}],"collection":[{"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/comments?post=576"}],"version-history":[{"count":0,"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/posts\/576\/revisions"}],"wp:attachment":[{"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/media?parent=576"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/categories?post=576"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/tags?post=576"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}