web-dev-qa-db-ja.com

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;

この中間部分について考えないでください..それの目的は別のものです...

私の問題は、LookupExecutableクラスのExecute()メソッドにあります。 TSelectionタイプの新しいインスタンスを作成し、それに値を割り当てる方法がわかりません。このTSelectionタイプは、常に匿名タイプです。

12
Sency

編集:この質問は XY問題 の代表的な例だと思います。正しい解決策は、ExpandoObjectまたは匿名の型に関係する必要はなく、関係がある場合はおそらく間違っているでしょう。


あなたはそれを間違った方法で見ています。匿名オブジェクトのインスタンスを作成する必要はありません。式で渡されるコードを呼び出す必要があります(匿名オブジェクトを作成する場合と作成しない場合があります)。

TEntitySourceのインスタンスを作成できる場合、それは簡単です: Compile()Select()で取得したExpression次に、TEntitySourceのインスタンスごとに呼び出します。

TEntitySourceを作成できない場合でも、入力がExpressionにならないように、ExpressionVisitorを(TEntitySourceを使用して)書き換えることで作成できます。しかし、あなたが持っているいくつかのタイプ。しかし、それはあなたからのいくらかの仕事を必要とするでしょう。


元の回答:

いいえ、それは機能しません。これは、C#でキャストまたは匿名型がどのように機能するかではありません。

2つのタイプ間でキャストして、機能することを期待することはできません。キャストするオブジェクトは、キャスト先のタイプである必要があります。または、2つのタイプのいずれかで、一致するキャスト演算子を指定する必要があります。

ターゲット型が匿名型であるという事実は何も変更しません(名前を付けることができないため、匿名型に直接キャストすることさえできないことを除いて; typeof() 間違っている)。

ソースタイプがdynamicであるという事実は、状況を少し変えます。ただし、キャスト演算子の検索はコンパイル時ではなく実行時に行われ、実行時にキャスト演算子を作成することもできます( DynamicObject.TryCast() を参照)。しかし、それだけです。「魔法の」キャスト演算子は追加されません。

このような動作を想像できる唯一の方法は、 「例によるキャスト」 とリフレクションのバリアントを使用した場合です。

_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も返すことを意味するためです。

4
svick

次のように、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;
    }

これでうまくいくはずです。

5
Minas

ここに、ExpandoObjectからのオブジェクトmadreがあります

        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;

Dynamycオブジェクトは、型指定されたDicionaryに簡単にキャストできます。

お役に立てば幸いです。

1
David Diez