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

请注意,第二种类型是内部的,如果我将其添加到代码中,则不会编译。我试图投到dynamicobject但都给我错误,说保护级别是不允许的

我需要一种方法来以某种方式迭代返回的字典。

4

2 回答 2

1

内部类型是不暴露在程序集之外的类型,私有嵌套类型受到更多限制。

正如您所说,您已经尝试过dynamic并且object遇到了错误,这里我使用一个示例来表示您的问题并演示您如何做到这一点。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 回答
1

找到了解决方案!

字典键是类型。还有另一个属性列出了类型,并且很容易转换为IEnumerable,因为System.Type是公共的。然后在 foreach 循环中,我能够迭代类型。同时,我可以调用字典的内部“get_item”函数,将类型作为参数传递。

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

正如 Jon 在下面所说,这非常脆弱,因为我依赖于内部实现细节,将来可能会发生变化。这不是一个好的解决方案。不幸的是,到目前为止,我还没有找到一种以更优雅的方式获取所需信息的方法。也许,我可以让 Microsoft 知道我需要以更公开的方式为内部EntityTypeConfiguration类型公开此元信息。但是,在他们倾听之前,我别无选择。

这是用于收集由 Code-First EntityFramework Fluent API 设置的模式信息的设计时工具所必需的。在此之前,我实现了一套包装类来替换遵循 Wrapper-Delegation 模式的EntityTypeConfiguration ,我可以在其中存储我需要的元数据。使用此模式时,我自己和用户都有更多的责任(即,对于地图类,用户被迫从我的自定义实现 EntityTypeMetaConfiguration 继承,对于数据库上下文类,我需要我的 [ DbMetaContext : DbContext],更不用说需要对OnModelCreating使用不同的覆盖)。

于 2013-07-02T23:25:48.860 回答