EDIT: I think this question is a prime example of the XY problem. The correct solution doesn't need to concern itself with ExpandoObject
or anonymous types, and it would be most likely wrong if it did.
You're looking at it the wrong way. You don't need to create an instance of an anonymous object, you need to invoke the code that is passed to you in an expression (which may or may not be creating an anonymous object).
If you can create an instance of TEntitySource
, then that's simple: Compile()
the Expression
that you got in Select()
and then invoke it for each instance of TEntitySource
.
If you can't create TEntitySource
, you could still do it by rewriting the Expression
(using ExpressionVisitor
), so that its input is not TEntitySource
, but some type you have. But that would require some work from you.
Original answer:
No, that won't work. That's simply not how casting or anonymous types work in C#.
You can't cast between any two types and expect it to work. Either the object you're casting needs to be the type you're casting to, or one of the two types needs to specify a matching cast operator.
The fact that the target type is an anonymous type doesn't change anything (except that you can't even try to cast to an anonymous type directly, because you can't name it; the way you're using typeof()
is wrong).
The fact that the source type is dynamic
changes things a bit. But only in that the search for the cast operator is done at runtime, not at compile time, and you can even create the cast operator at runtime (see DynamicObject.TryCast()
). But that's it, it doesn't add any “magical” cast operators.
The only way I can imagine something like this working would be if you used a variant of “cast by example” and reflection:
public T Convert<T>(ExpandoObject source, T example)
where T : class
{
IDictionary<string, object> dict = source;
var ctor = example.GetType().GetConstructors().Single();
var parameters = ctor.GetParameters();
var parameterValues = parameters.Select(p => dict[p.Name]).ToArray();
return (T)ctor.Invoke(parameterValues);
}
You could then use it something like this:
var expando = new ExpandoObject();
dynamic dynamicExpando = expando;
dynamicExpando.Foo = "SomeString";
dynamicExpando.Bar = 156;
var result = Convert(expando, new { Foo = "", Bar = 1 });
Note that you can't actually invoke Convert()
dynamically (by passing it dynamicExpando
), because that would mean it would return dynamic
too.