2

があり、DynamicObjectとまったく同じように IDictionary にキャストできるようにしたいExpandoObject。たとえば、 ExpandoObject を IDictionary にキャストすることは完全に有効です。

dynamic ex = new ExpandoObject ();
ex.Field = "Foobar";
IDictionary<string, object> dict = ex as IDictionary<string, object>;
Console.WriteLine (dict["Field"]);

これを自分の DynamicObject に実装してみます。

public class MyDynamicObject : DynamicObject
{
    public Dictionary<string, object> members = new Dictionary<string, object> ();

    public override bool TryGetMember (GetMemberBinder binder, out object result)
    {
        if (members.ContainsKey (binder.Name)) {
            result = members[binder.Name];
            return true;
        }
        else {
            result = null;
            return false;
        }
    }
    public override bool TrySetMember (SetMemberBinder binder, object value)
    {
        this.members.Add (binder.Name, value);
        return true;
    }
    public static implicit operator IDictionary<string, object> (MyDynamicObject mydo) 
    {
        return (IDictionary<string, object>) mydo.members;
    }
}

しかし、コンパイラはそのpublic static implicit operator IDictionary<string, object>行で失敗し、次のエラーが表示されます:「インターフェイス型との間で変換できません」。暗黙の演算子を Dictionary に変更すると、MyDynamicObject を問題なく Dictionary にキャストできますが、IDictionary にはキャストできません。

ExpandoObject はどのようにこれを行いますか?

4

3 に答える 3

8

ExpandoObjectを実装するだけIDictionary<string, object>です。

同じ動作が必要な場合は、このインターフェイスを実装し、すべての呼び出しをmembersフィールドに委任する必要もあります。

このようなもの:

public class MyDynamicObject : DynamicObject, IDictionary<string, object>
{
    public Dictionary<string, object> members = new Dictionary<string, object>();

    public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
    {
        return members.GetEnumerator();
    }

    public void Add(KeyValuePair<string, object> item)
    {
        members.Add(item.Key, item.Value);
    }

    // ...
}
于 2012-08-31T07:52:30.900 に答える
0

キャスト演算子は DLR によって問い合わせられないため、これは機能しません。

メソッドを継承することも、メソッドIDictionaryをオーバーライドすることもできますTryConvert

実装IDictionaryには、多くの操作を実装するかスタブ化する必要があるため、TryConvertルートの方が実際には実装が簡単であることに気付くかもしれません。欠点は、実装では、TryConvert呼び出すたびに辞書の新しいインスタンスがほぼ確実に生成されるため (結果をキャッシュして最新の状態に保たない限り)、パフォーマンスがさらに低下する可能性があることです。

于 2012-08-31T07:54:42.110 に答える
0

C# 仕様で定義されています。

クラスまたは構造体は、ソースの型 S からターゲットの型 T への変換を宣言することが許可されています。

  • ...
  • S も T もobject、またはinterface-typeではありません。

このスタック オーバーフローの回答を参照してください。

于 2012-08-31T07:55:59.520 に答える