1

匿名オブジェクトの複雑な構造をオブジェクト内で公開するにはどうすればよいdynamicですか?

匿名オブジェクトは としてフラグが付けられているため、これを回避internalする創造的な方法を探しています。

// This is the library I control
public void SendObject() {
    var anonymous = new {
        Text = "Test",
        SubItem = new {
            SubText = "Bla",
            SubSub = new {
                SubSubText = "Baha"
            }
        }
    };
}

dynamic dyn = ExposeAnonymous(anonymous); // Perform voodoo

var result = ExternalLibrary.GetSpecialProperty(dyn);

// External library I don't control
public object GetSpecialProperty(dynamic dyn) {
    return dyn.SubItem.SubSub.SubSubText;
}

問題は、私が制御していない他の外部ライブラリにを送信するdynamicと、次のようなエラーが発生することです。

「オブジェクト」には「サブアイテム」の定義が含まれていません。

4

3 に答える 3

6

問題は、ダイナミックを他のライブラリに送信するときです。

...そして、摩擦があります。匿名型はinternal、C# コンパイラによって宣言されます。つまり、他のアセンブリはそれらにアクセスできません。

匿名型の使用を停止するか、使用[InternalsVisibleToAttribute]して型を他のアセンブリに表示できるようにします。匿名型のインスタンスを作成する型を含むアセンブリ内で、次を使用します。

[InternalsVisibleTo("ExternalLibrary")]

(私は実際には問題がオンになっていることを期待していSubItemますSubSub...)

于 2013-04-23T15:35:15.550 に答える
5

匿名型はinternalあり、DLR は、コンパイラがコンパイル時に行うのと同じアクセシビリティ分析を実行時に行います。したがって、を使用して別のアセンブリから匿名型のメンバーにアクセスすることはできませんdynamic

1つのオプションは、次を使用することExpandoObjectです。

        dynamic a = new ExpandoObject();
        a.Text = "Test";
        a.SubItem = new ExpandoObject();
        a.SubItem.SubText = "Blah";
        a.SubItem.SubSub = new ExpandoObject();
        a.SubItem.SubSub.Text = "Baha";

これは見苦しいので、匿名型を保持し、ヘルパー メソッドを使用して再帰的に に変換できますExpandoObject

    public static dynamic ConvertToExpando(object obj)
    {
        IDictionary<string, object> expando = new ExpandoObject();
            foreach(var pi in obj.GetType().GetProperties())
            {
                // there doesn't seem to be a way to know if it is an anonymous type directly. So I use IsPublic here.
                if (pi.PropertyType.IsPublic)
                {
                    expando[pi.Name] = pi.GetValue(obj);                    
                }
                else
                {
                    expando[pi.Name] = ConvertToExpando(pi.GetValue(obj));
                }
            }
        return expando;
    }

これは、必要な「ブードゥーを実行する」ことを行います。

于 2013-04-23T15:54:05.730 に答える
1

私のオープンソース フレームワーク ImpromptuInterface (ナゲット内) を使用すると、インライン構文で複雑な展開グラフを作成できます。

dynamic New = Builder.New<ExpandoObject>();

dynamic dyn = New.Obj(
        Text: "Test",
        SubItem: New.Obj(
            SubText: "Bla",
            SubSub: New.Obj(
                SubSubText: "Baha"
            )
        )
    );
于 2013-05-02T12:48:26.287 に答える