Привести ExpandoObject к анонимному типу

Могу ли я привести ExpandoObject к анонимному типу?

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

Добавлено позже

// Это моя сущность

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;

Не думайте об этой средней части ... Цель другая ...

Моя проблема в методе Execute () в классе LookupExecutable. Я не знаю, как создать новый экземпляр типа TSelection и присвоить ему значения. Этот тип TSelection всегда является анонимным.


person Sency    schedule 20.04.2012    source источник
comment
Как вы думаете, почему вы хотите делать то, что думаете?   -  person Ramesh    schedule 20.04.2012
comment
Я хочу динамически создавать анонимный тип и динамически присваивать ему значения.   -  person Sency    schedule 20.04.2012
comment
@KushanFernando, но почему? Что ты хочешь с этим делать?   -  person svick    schedule 20.04.2012
comment
Это связано с stackoverflow.com/questions/10240487/ вопрос. но SO закрыл этот вопрос. Как создать новый экземпляр универсального типа (TResult), который всегда будет анонимно типизирован. и как присвоить значения свойствам этого нового экземпляра?   -  person Sency    schedule 20.04.2012
comment
Похоже, вы не понимаете, что такое анонимность.   -  person Andrew Barber    schedule 20.04.2012
comment
Даже если вы можете привести к анонимному типу, они все равно всегда доступны только для чтения ... пожалуйста, дайте нам больше информации о более широкой картине того, что вы пытаетесь достичь, а не так, как вы думал об этом.   -  person Jon Skeet    schedule 20.04.2012
comment
Хорошо, Джон, я печатаю здесь все ... дай мне минутку.   -  person Sency    schedule 20.04.2012
comment
Скорее наоборот: как-сделать-и-перебирать-свойства-анонимного-объекта-в-c   -  person nawfal    schedule 28.06.2014


Ответы (3)


РЕДАКТИРОВАТЬ: Я думаю, что этот вопрос является ярким примером проблема XY. Правильное решение не обязательно должно касаться ExpandoObject или анонимных типов, и, скорее всего, оно было бы неправильным.


Вы неправильно смотрите на это. Вам не нужно создавать экземпляр анонимного объекта, вам нужно вызывать код, который передается вам в выражении (которое может создавать или не создавать анонимный объект).

Если вы можете создать экземпляр TEntitySource, это просто: Compile() Expression, который вы получили в Select(), а затем вызывайте его для каждого экземпляра TEntitySource.

Если вы не можете создать TEntitySource, вы все равно можете сделать это, переписав Expression (используя ExpressionVisitor) так, чтобы его ввод был не TEntitySource, а каким-то типом, который у вас есть. Но это потребует от вас некоторой работы.


Исходный ответ:

Нет, это не сработает. Это просто не то, как работает приведение типов или анонимные типы в C #.

Вы не можете выбрать между любыми двумя типами и ожидать, что это сработает. Либо объект, который вы приводите, должен быть того типа, к которому вы приводите приведение, либо один из двух типов должен указывать соответствующий оператор приведения.

Тот факт, что целевой тип является анонимным, ничего не меняет (за исключением того, что вы даже не можете пытаться выполнить приведение к анонимному типу напрямую, потому что вы не можете назвать его; то, как вы используете typeof(), неверно) .

Тот факт, что тип источника dynamic, немного меняет ситуацию. Но только в том случае, если поиск оператора приведения выполняется во время выполнения, а не во время компиляции, и вы даже можете создать оператор приведения во время выполнения (см. _ 13_). Но это все, он не добавляет никаких «волшебных» операторов приведения.

Единственный способ, которым я могу представить себе что-то подобное, - это использовать вариант «приведение по примеру» и отражение:

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);
}

Затем вы можете использовать это примерно так:

var expando = new ExpandoObject();
dynamic dynamicExpando = expando;
dynamicExpando.Foo = "SomeString";
dynamicExpando.Bar = 156;
var result = Convert(expando, new { Foo = "", Bar = 1 });

Обратите внимание, что вы не можете вызывать Convert() динамически (передавая dynamicExpando), потому что это будет означать, что он тоже вернет dynamic.

person svick    schedule 20.04.2012
comment
Большое спасибо, svick. Я застрял в этом больше 2 недель. На самом деле ваш метод Convert работает хорошо ... но мне пришлось удалить ограничение where. Еще раз спасибо за ваши усилия по пониманию моего вопроса. - person Sency; 20.04.2012

Используйте JavaScriptSerializer для преобразования ExpandoObject в любой тип следующим образом:

.....
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;
    }

Это должно сработать.

person Minas    schedule 03.04.2014
comment
Это не то, что он ищет. Это специально для анонимного типа. - person sports; 03.01.2015

здесь у вас есть объект из ExpandoObject

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

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

Но будьте осторожны, динамические объекты очень дороги в ресурсах, и то, что вы просите, кажется бессмысленным. Хороший подход к тому, о чем вы спрашиваете в комментариях, предполагая, что вам нужно иметь дело с динамическими объектами и вы хотите что-то с ними сделать:

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

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

myObj["myProperty"] = expando.myProperty;

Любой динамический объект легко преобразовать в типизированный словарь.

Надеюсь, это поможет!

person David Diez    schedule 20.04.2012