Cast ExpandoObject to anonymous type
Asked Answered
E

3

14

Can I cast ExpandoObject to anonymous type ?

var anoObj = new { name = "testName", email = "testEmail" };

dynamic expandoObj = new System.Dynamic.ExpandoObject();

// Here I'm populating the expandoObj with same property names/types in anonymoustype(anoObj)

// Now, how to convert this ExpandoObject to anonymoustype ?

var newObj = (typeof(anoObj)expandoObj); // This doesn't work

Added Later

// This is my entity

public class Customer
    {
        #region Public Properties

        [ColumnAttribute(Name = "IdColumn")]
        public string Id { get; set; }

        [ColumnAttribute(Name = "NameColumn")]
        public string Name { get; set; }

        [ColumnAttribute(Name = "AddressColumn")]
        public string Address { get; set; }

        [ColumnAttribute(Name = "EmailColumn")]
        public string Email { get; set; }

        [ColumnAttribute(Name = "MobileColumn")]
        public string Mobile { get; set; } 

        #endregion
    }

// -------------------------------------------------------------------------------------

public class LookupService<TEntitySource>
{
    public LookupService ()
    {

    }

    public LookupShowable<TEntitySource, TSelection> Select<TSelection>(Expression<Func<TEntitySource, TSelection>> expression)
    {
        var lookupShowable = new LookupShowable<TEntitySource, TSelection>();

        return lookupShowable;
    }
}

public class LookupShowable<TEntitySource,TSelection>
{
    public LookupShowable()
    {

    }

    public LookupExecutable<TEntitySource, TSelection, TShow> Show<TShow>(Expression<Func<TEntitySource, TShow>> expression)
    {
        var lookupExecutable = new LookupExecutable<TEntitySource,TSelection,TShow>();

        return lookupExecutable;
    }
}

public class LookupExecutable<TEntitySource, TSelection, TShow>
{
    public TSelection Execute()
    {
       // Here I want to create a new instance of TSelection and populate values from database and return it.
    }
}

//--------------------------------------------------------------------------------------

// This is How I want to call this from front end...
    var lookupService = new LookupService<Customer>();
    var lookupSelection = lookupService.Select(C => new { C.Id, C.Name, C.Mobile }).Show(C => new { C.Id, C.Name}).Execute();


    string sID = lookupSelection.Id;
    string sName = lookupSelection.Name;
    string sMobile = lookupSelection.Mobile;

Dont think about this middle part.. Purpose of it is another one...

My problem is in Execute() method in LookupExecutable class. I dont know how to create a new instance of TSelection type and assign values to it. This TSelection type is always an anonymous type..

Elmaleh answered 20/4, 2012 at 7:11 Comment(8)
Why do you think you want to do what you think?Tupungato
I want to create an anonymous type dynamically and assign values to it dynamically.Elmaleh
@KushanFernando, but why? What do you want to do with it?Toponymy
This is related to #10240987 question. but SO has closed this question. How to create a new instance of generic type(TResult) which will always be an anonymous typed. and how to assign values to properties of this new instance ?Elmaleh
You don't seem to understand what "anonymous" means.Thessalonian
Even if you could cast to the anonymous type, they're always read-only anyway... please give us more information about the bigger picture of what you're trying to accomplish - not the way you thought of accomplishing it.Ellette
Ok Jon, Im typing the entire thing here.. gimme a min.Elmaleh
Somewhat an opposite: how-do-i-iterate-over-the-properties-of-an-anonymous-object-in-cStinkpot
T
10

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.

Toponymy answered 20/4, 2012 at 7:21 Comment(1)
Lots of thanks svick. I've been stucked with this morethan 2 weeks. Actually your Convert method working well.. but I had to remove the where constraint. Again thanks for your effort on understanding my question.Elmaleh
A
4

Use JavaScriptSerializer to convert the ExpandoObject to any Type as follows:

.....
dynamic myExpandoObject = new ExpandoObject();
var result = ConvertDynamic<myType>(myExpandoObject);
.....


    public T ConvertDynamic<T>(IDictionary<string, object> dictionary)
    {
        var jsSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
        var obj = jsSerializer.ConvertToType<T>(dictionary);
        return obj;
    }

This should do the job.

Atrip answered 3/4, 2014 at 5:16 Comment(1)
It is not "to any type" what he's looking. It is specifically "to anonymous type".Spectatress
T
1

here you have an object made from an ExpandoObject

        var anoObj = new { name = "testName", email = "testEmail" };

        dynamic expandoObj = new System.Dynamic.ExpandoObject();
        object newObj = expandoObj;

But beware, dynamic objects are very very expensive in resource matters, and what you are asking for does not seem to have any sense. A good aproach for what you are asking in the comments supposing you have to deal with dynamic objects and you want to do something with them:

dynamic expando = new System.Dynamic.ExpandoObject();

var myObj = new Dictionary<string, object>();

myObj["myProperty"] = expando.myProperty;

Any dynamyc object is easily casted to a <string, object> typed Dicionary.

Hope that helps!

Tattoo answered 20/4, 2012 at 7:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.