没有问题
我很容易得到一个私有的嵌套属性。
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
请注意,第二种类型是内部的,如果我将其添加到代码中则不会编译。我试图转发dynamic
和object
,但两者都给我错误,说不允许保护等级。
我需要一种方法以某种方式迭代返回的dicationary。
答案 0 :(得分:1)
Internal types是未在程序集外公开的类型,而私有nested types则更受限制。
正如您所说,您已尝试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
的成员,它将在运行时抛出。
正如您所看到的,如果您测试了代码,它运行没有问题。令人讨厌的是,你需要通过反映字典的值来做所有事情。
答案 1 :(得分: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.
}
正如乔恩在下面所说,这非常脆弱,因为我依赖内部实施细节,可能会在未来发生变化。这不是一个好的解决方案。不幸的是,到目前为止,我还没有找到一种以更优雅的方式获取所需信息的方法。也许,我可以让微软知道我需要以更公开的方式为内部 EntityTypeConfiguration 类型公开这个元信息。但是,直到他们听,我才剩下几个选择。
这是设计时工具所需,用于收集Code-First EntityFramework Fluent API设置的架构信息。在此之前,我实现了一套包装类,它们取代了 EntityTypeConfiguration ,它遵循Wrapper-Delegation模式,我可以将我需要的元数据放在一边。使用此模式时,我自己和用户都有更多的责任(即,对于Map Classes,用户必须从我的自定义实现EntityTypeMetaConfiguration继承,对于数据库上下文类,我的[ DbMetaContext :DbContext]是必要的,更不用说为 OnModelCreating 使用不同的覆盖。