1

タイプに到達するのに問題はありません

本質的にプライベートなネストされたプロパティに簡単にアクセスできます。

var modelConfigurationFieldInfo=
        _modelBuilder.Configurations.GetType().GetField(
            "_modelConfiguration",
            System.Reflection.BindingFlags.NonPublic
            |System.Reflection.BindingFlags.Instance
            );

var modelConfiguration=
        modelConfigurationFieldInfo.GetValue(
            _modelBuilder.Configurations);

var entityConfigurationsFieldInfo=
        modelConfiguration.GetType().GetField(
            "_entityConfigurations",
            System.Reflection.BindingFlags.NonPublic
            |System.Reflection.BindingFlags.Instance
            );

var entityConfigurations=
        entityConfigurationsFieldInfo.GetValue(modelConfiguration);

問題はmy _entityConfigurations、次のタイプです。

Dictionary`Type、System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration

2 番目のタイプは内部的なものであり、コードに追加するとコンパイルされないことに注意してください。dynamicandにキャストしようとしましたが、どちらもthe protection level is not allowed というobjectエラーが表示されます。

返された辞書を何らかの形で反復する方法が必要です。

4

2 に答える 2

1

解決策を見つけました!

ディクショナリ キーは type でした。System.Typeが public であるため、タイプをリストし、IEnumerableに簡単にキャストできる別のプロパティがありました。次に、 foreach ループで型を反復処理できました。同時に、型をパラメータとして渡すディクショナリの内部「get_item」関数を呼び出すことができました。

foreach(var type in types) 
{ 
    var data = entityConfigurations.GetType().GetMethod("get_Item")
                    .Invoke(new object[] { type });
    // Get more information here.
}

Jon が以下で述べたように、将来変更される可能性がある内部実装の詳細に依存しているため、これは非常に脆弱です。これは良い解決策ではありません。残念ながら、これまでのところ、必要な情報をよりエレガントな方法で取得する方法は見つかりませんでした。おそらく、内部のEntityTypeConfiguration型のために、このメタ情報をより一般的な方法で公開する必要があることを Microsoft に知らせることができます。しかし、彼らが耳を傾けるまで、私にはいくつかの選択肢が残されています。

これは、Code-First EntityFramework Fluent API によって設定されたスキーマ情報の収集に使用される設計時ツールに必要です。これに先立って、 EntityTypeConfigurationを置き換える一連のラッパー クラスを実装しました。これは、必要なメタデータを削除できる Wrapper-Delegation パターンに従いました。このパターンを使用する場合、自分自身とユーザーの両方に、より多くの責任があります (つまり、マップ クラスの場合、ユーザーはカスタム実装 EntityTypeMetaConfiguration から継承することを余儀なくされ、データベース コンテキスト クラスの場合、my [ DbMetaContext : DbContext] が必要です。OnModelCreatingに別のオーバーライドを使用する必要があります)。

于 2013-07-02T23:25:48.860 に答える
1

内部型は、アセンブリの外部に公開されない型であり、入れ子になったプライベート型はさらに制限されています。

試してみてエラーが発生したと述べたようにdynamicobjectここでは例を使用して問題を表し、どのようにそれを行うことができるかを示しています。System.Array.ArrayEnumerator代わりに、フレームワークに付属するネストされたプライベート クラスを使用しました。

public static partial class TestClass {
    public static void TestMethod() {
        var internalType=
                typeof(Array).GetNestedType(
                    "ArrayEnumerator", BindingFlags.NonPublic);

        var x=new SampleClass();
        var type=x.GetType();
        var bindingAttr=BindingFlags.Instance|BindingFlags.NonPublic;
        var info=type.GetField("dict", bindingAttr);
        var dict=info.GetValue(x) as IDictionary<Type, object>;
        var arrayEnumerator=dict[internalType];
    }
}

partial class SampleClass {
    public SampleClass() {
        var internalType=
                typeof(Array).GetNestedType(
                    "ArrayEnumerator", BindingFlags.NonPublic);

        var invokeAttr=
                BindingFlags.CreateInstance|
                BindingFlags.Instance|
                BindingFlags.NonPublic;

        var array=new[] { 1, 2, 3 } as IList;
        var args=new object[] { array, 0, array.Count };

        var arrayEnumerator=
                internalType.InvokeMember(
                    ".ctor", invokeAttr, null, null, args);

        dict.Add(internalType, arrayEnumerator);
    }

    Dictionary<Type, object> dict=new Dictionary<Type, object>();
}

前に述べたように、入れ子になったプライベート型はより制限されています。私のコードは の使用を許可されておらずArray.ArrayEnumerator、コンパイル時にその情報が得られなかったため、object選択されました。dynamicのメンバーにアクセスしようとすると、実行時にスローされますArrayEnumerator

コードをテストした場合にわかるように、問題なく実行されます。煩わしいことは、辞書の値を使用してリフレクションを介してすべてを行う必要があることです。

于 2013-06-30T11:17:07.817 に答える