Given this method signature:
void Foo<T>(Func<T, object> expression) Is it possible to use reflection to create a type-representation of Func<dynamic, object> to use with MakeGenericType for the expression argument's type? The "obvious" approaches are not valid C# syntax because dynamic is neither a type nor an object (ie. typeof(dynamic) is invalid), so I've not been able to come up with anything useful for the ??? parameter below:
Type fnType = typeof(Func<,>).MakeGenericType(new Type[] { ???, typeof(object) }); Interestingly, I can do this and it compiles without errors, but the script compiler throws at runtime, I think because that typeof is really returning a Func<object, object>:
Type fn = typeof(Func<dynamic, object>); At least, anything I can find through reflection or the debugger seems indistinguishable from typeof(Func<object, object>). Of course, I realize dynamic is a special case in the C# language -- behind-the-scenes black-box "magic" behavior somehow attached to an object. The question, I suppose, is what makes that object special when I write something like this:
Foo<dynamic>(n => new { n.prop }); Since dynamic tends to generate a flurry of "your architecture sucks" replies, I'll preempt those by explaining the real-world scenario: I'm using the Roslyn Scripting API to load and compile expression delegates from configuration to filter, destructure, or otherwise alter various objects (including anonymous types, hence dynamic) written to a structured logger (Serilog).
I am starting to think this is an edge-case that reflection just can't handle. (I've been hoping to avoid Expressions, but I'm wondering if that could pull it off somehow.)
Edit: Real Code
Sample inputs (that actually work) might be Sample.Account (a class in my test console program) and a => new { a.Username } as the transformation expression to compile, demonstrating a common structured-logging example of an account class storing a username and password, and you use destructuring to strip the password. (I've already populated ScriptingOptions with the necessary assembly references and imports before this is called.)
The output from this (using the inputs described above) would be an instance of Func<Sample.Account, object>. The question is how to do this sort of thing to obtain Func<dynamic, object> as the output (which can be written and compiled as source, but as far as I can tell, can't be set up through reflection).
private static dynamic CompileTransformation(string transformedType, string transformation) { // get a Type that corresponds to namespace.type in transformedType Type TValue = Type.GetType(transformedType) ?? AppDomain.CurrentDomain.GetAssemblies() .Select(a => a.GetType(transformedType)) .FirstOrDefault(t => t != null); // get a representation of Func<TValue, object> Type funcType = typeof(Func<,>).MakeGenericType(new Type[] { TValue, typeof(object) }); // get a representation of CSharpScript.EvaluateAsync<Func<TValue, object>>() var evalMethod = typeof(CSharpScript).GetMethods() .FirstOrDefault(m => m.Name.Equals("EvaluateAsync") && m.IsGenericMethod) .MakeGenericMethod(funcType); // execute EvaluateAsync dynamic evalTask = evalMethod.Invoke(null, new object[] { transformation, ReflectionHelper.scriptOptions, null, null, null }); dynamic compiledFunc = evalTask.GetAwaiter().GetResult(); return compiledFunc; }
typeof(ExpandoObject)for your???- I doubt it will work but worth checking...? Regardless, please could you update the question with an MVCE (yes - a non-compiling one with a placeholder marked as???) so that we can try out solutions (and more easily understand the exact nature of your question) ourselves before suggesting them :)ExpandoObjectwould fill the bill... the object isn't always an anonymous type, and if I remember correctly, one of the other thingsdynamiccan do is (somehow) act as a wrapper around a concrete type (sounds sort of like boxing-for-objects).objectas "dynamic-capable" for lack of a better term. So in effect, I'm looking for a way to do the same thing at runtime. I won't be too surprised if it simply isn't possible, but I wanted a more authoritative answer than, "I couldn't figure it out." :)Func<dynamic, object> M() => n => new { n.prop };compiles to the exact same IL asFunc<object, object> M() => n => new { ((dynamic) n).prop };.dynamicproperty access is implemented by calls to the DLR and is completely different from the direct property access using reflection you're used to.