{"id":334,"date":"2009-04-21T22:33:07","date_gmt":"2009-04-21T21:33:07","guid":{"rendered":"http:\/\/www.gamlor.info\/wordpress\/?p=334"},"modified":"2021-03-11T09:44:25","modified_gmt":"2021-03-11T08:44:25","slug":"why-i-cant-wait-to-get-dynamic-in-c","status":"publish","type":"post","link":"https:\/\/www.gamlor.info\/wordpress\/2009\/04\/why-i-cant-wait-to-get-dynamic-in-c\/","title":{"rendered":"Why I can\u2019t wait to get dynamic in C#"},"content":{"rendered":"<p>Just wrote again really ugly reflection based code. In such moments I really wish that the \u2018dynamic\u2019-type is already here.<\/p>\n<p>I wanted to make this statement, but replace the MyServiceResolvedAtRuntime and ArgumentTypeResolvedAtRuntime with type I only know at runtime.<\/p>\n<div style=\"overflow: auto\">\n<pre class=\"csharpcode\"><span class=\"kwrd\">private<\/span> <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">void<\/span> BuildArgumentProvider(ContainerBuilder builder)\r\n        {\r\n            builder.Register&lt;Provider&lt;MyServiceResolvedAtRuntime, ArgumentTypeResolvedAtRuntime&gt;&gt;(\r\n                ctx =&gt; argument\r\n                       =&gt; ctx.Resolve&lt;MyServiceResolvedAtRuntime&gt;(<span class=\"kwrd\">new<\/span>[] { <span class=\"kwrd\">new<\/span> NamedPropertyParameter(<span class=\"str\">\"param\"<\/span>, argument) }))\r\n                .As&lt;Provider&lt;MyServiceResolvedAtRuntime, ArgumentTypeResolvedAtRuntime&gt;&gt;();\r\n        }<\/pre>\n<\/div>\n<p>As you may noticed, there are lots of generics and closures involved. So with reflection the whole thing just explodes. Yes, I\u2019m not a .NET-Reflection expert, it\u2019s certainly possible to improve it. But even if you improve it a lot, it still will be ugly.\u00a0 Anyway, I ended with this code:<\/p>\n<div style=\"overflow: auto\">\n<pre class=\"csharpcode\"><span class=\"kwrd\">public<\/span> AttributeBasedModule{\r\n<span class=\"rem\">\/** snip **\/<\/span>\r\n        <span class=\"kwrd\">private<\/span> <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">void<\/span> BuildArgumentProvider(ConstructorInfo info, Type descriptor, ContainerBuilder builder)\r\n        {\r\n            <span class=\"rem\">\/** snip **\/<\/span>\r\n            ParameterInfo info = <span class=\"rem\">\/** snip **\/<\/span>\r\n            var typeToRegister = <span class=\"kwrd\">typeof<\/span>(Provider&lt;,&gt;).MakeGenericType(<span class=\"kwrd\">new<\/span>[] { descriptor, argument.ParameterType });\r\n            builder.Register&lt;<span class=\"kwrd\">object<\/span>&gt;(ctx =&gt; CreateCreationArgsResolver(typeToRegister,ctx, descriptor,argument))\r\n                .As(typeToRegister);\r\n\r\n        }\r\n\r\n        <span class=\"kwrd\">static<\/span> Delegate CreateCreationArgsResolver(Type typeToRegister,IContext ctx, Type serviceType,ParameterInfo argument)\r\n        {\r\n            var ctxKeeper = ContextKeeper.CreateGeneric(ctx,\r\n                (creationContext, arg)\r\n                    =&gt; creationContext.Resolve(serviceType,<span class=\"kwrd\">new<\/span> Parameter[]{<span class=\"kwrd\">new<\/span> NamedParameter(argument.Name,arg)})\r\n                    ,serviceType, argument.ParameterType);\r\n\r\n            <span class=\"kwrd\">return<\/span> Delegate.CreateDelegate(typeToRegister, ctxKeeper, ReflectionInvokedMethodName);\r\n        }\r\n\r\n        <span class=\"rem\">\/\/\/ &lt;summary&gt;<\/span>\r\n        <span class=\"rem\">\/\/\/ Build the generic version to allow the binding to a particular delegate.<\/span>\r\n        <span class=\"rem\">\/\/\/ &lt;\/summary&gt;<\/span>\r\n        <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">class<\/span> ContextKeeper\r\n        {\r\n            <span class=\"kwrd\">internal<\/span> <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">object<\/span> CreateGeneric(IContext ctx, Func&lt;IContext, <span class=\"kwrd\">object<\/span>, <span class=\"kwrd\">object<\/span>&gt; invoker, Type service, Type parameter)\r\n            {\r\n                var genericType = <span class=\"kwrd\">typeof<\/span> (ContextKeeper&lt;,&gt;).MakeGenericType(<span class=\"kwrd\">new<\/span>[] {service, parameter});\r\n                var constructor = genericType.GetConstructor(<span class=\"kwrd\">new<\/span>[] {<span class=\"kwrd\">typeof<\/span> (IContext), <span class=\"kwrd\">typeof<\/span> (Func&lt;IContext, <span class=\"kwrd\">object<\/span>, <span class=\"kwrd\">object<\/span>&gt;)});\r\n                <span class=\"kwrd\">return<\/span> constructor.Invoke(<span class=\"kwrd\">new<\/span> <span class=\"kwrd\">object<\/span>[] {ctx,invoker});\r\n            }\r\n        }\r\n        <span class=\"rem\">\/\/\/ &lt;summary&gt;<\/span>\r\n        <span class=\"rem\">\/\/\/ Keeping the context for the actual invoker. Represent the context-keeping behavior of closures<\/span>\r\n        <span class=\"rem\">\/\/\/ &lt;\/summary&gt;<\/span>\r\n        <span class=\"rem\">\/\/\/ &lt;typeparam name=\"TService\"&gt;The service to create&lt;\/typeparam&gt;<\/span>\r\n        <span class=\"rem\">\/\/\/ &lt;typeparam name=\"TArgument\"&gt;The constructor-argument for the service&lt;\/typeparam&gt;<\/span>\r\n        <span class=\"kwrd\">class<\/span> ContextKeeper&lt;TService,TArgument&gt;\r\n        {\r\n            <span class=\"kwrd\">private<\/span> <span class=\"kwrd\">readonly<\/span> IContext ctx;\r\n            <span class=\"kwrd\">private<\/span> <span class=\"kwrd\">readonly<\/span> Func&lt;IContext, <span class=\"kwrd\">object<\/span>, <span class=\"kwrd\">object<\/span>&gt; invoker;\r\n\r\n            <span class=\"kwrd\">public<\/span> ContextKeeper(IContext ctx, Func&lt;IContext, <span class=\"kwrd\">object<\/span>, <span class=\"kwrd\">object<\/span>&gt; invoker)\r\n            {\r\n                <span class=\"kwrd\">this<\/span>.ctx = ctx;\r\n                <span class=\"kwrd\">this<\/span>.invoker = invoker;\r\n            }\r\n\r\n            <span class=\"rem\">\/\/\/ &lt;summary&gt;<\/span>\r\n            <span class=\"rem\">\/\/\/ Is invoked by reflection, see &lt;see cref=\"ReflectionInvokedMethodName\"\/&gt;<\/span>\r\n            <span class=\"rem\">\/\/\/ &lt;\/summary&gt;<\/span>\r\n            <span class=\"rem\">\/\/\/ &lt;param name=\"arg\"&gt;&lt;\/param&gt;<\/span>\r\n            <span class=\"rem\">\/\/\/ &lt;returns&gt;&lt;\/returns&gt;<\/span>\r\n            <span class=\"kwrd\">public<\/span> TService Invoke(TArgument arg)\r\n            {\r\n                <span class=\"kwrd\">return<\/span> (TService)invoker.Invoke(ctx, arg);\r\n            }\r\n        }\r\n}<\/pre>\n<\/div>\n<p>The .NET 4.0 dynamic-type will\u00a0 make reflection a lot easier. Event more, it will make any calls to dynamic typed stuff like REST-Services, Ruby, JavaScript, XML with no schema,\u00a0 data-stores etc. a pleasure.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Just wrote again really ugly reflection based code. In such moments I really wish that the \u2018dynamic\u2019-type is already here. I wanted to make this statement, but replace the MyServiceResolvedAtRuntime&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[126,17],"tags":[21,24],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/334"}],"collection":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/comments?post=334"}],"version-history":[{"count":14,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/334\/revisions"}],"predecessor-version":[{"id":3799,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/334\/revisions\/3799"}],"wp:attachment":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/media?parent=334"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/categories?post=334"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/tags?post=334"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}