我想动态读取我在循环通过父实体的PropertyInfos时遇到的EntityObjects的PropertyInfos的值(连接到当前Image实例的ImageType实例的列值,fi)
主要实体的类型仅在运行时已知,因此我正在寻找一种读取任何引用的实体对象的PropertyInfo值的通用方法。
我可以遍历子实体的PropertyInfos,但是当我尝试获取值时,我得到一个TargetException:Object与目标类型不匹配。
// loop through the main entity's properties
foreach (PropertyInfo pi in entityType.GetProperties())
{
// if the main entity's property is an entity
if (pi.PropertyType.BaseType == typeof(System.Data.Objects.DataClasses.EntityObject))
{
// loop through the sub entity's properties
foreach(PropertyInfo mychildren in pi.PropertyType.GetProperties())
{
// the loop works fine but when i try to get a value I get a
// TargetException: Object does not match target type.
object test = mychildren.GetValue(pi, null);
}
}
}
我该怎么做?
修改:
Entity Framework 4.0似乎不允许您动态检索实体相关实体的实例。但是使用EF 4.1及更高版本,您可以使用其类名作为字符串标识符。所以我升级到EF 4.2并开始工作。
我想要这段代码的原因是在我的DTO翻译例程中使用它。我的DTO可以具有与相关实体的名称属性相对应的字符串属性,这样我就可以访问这些属性而无需对相关实体的类型进行硬编码。
在EF 4.1及更高版本中,ObjectContext由名为DbContext的类包装,该类提供导航属性,使用该属性可以使用字符串获取相关实体的实例。要动态检索单个相关实体,您可以使用:
dynamic refObject = Activator.CreateInstance(refObjectType);
refObject = context.Entry(currentObject).Reference(refObjectType.Name)。CurrentValue;
对于那些从4.0升级的人:使用DbContext的推荐方法不是使用EntityObjects而是使用POCO。这些可以手动完成,也可以通过edmx上下文菜单生成。
我目前的实施如下:
// Loop through the propertyinfos of the dto's type
foreach (PropertyInfo pf in dtoType.GetProperties().Where(p => p.CanWrite))
{
// Use the name of the dto property to get the corresponding property from the POCO's type. If it doesn't exist, pi will be null
PropertyInfo pi = pocoType.GetProperty(pf.Name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
if (pi != null)
{
// Check if the current propertyinfo of the POCO has a subproperty named Id
// If this is the case we treat the propertyinfo as a referenced POCO
if (pi.PropertyType.GetProperty("Id") != null)
{
// skip referenced POCOs if their data is not needed
if (!includeRelated) continue;
// Get the type of the referenced POCO
Type refObjectType = pi.PropertyType;
// Create an instance of the referenced POCO
dynamic refObject = Activator.CreateInstance(refObjectType);
// Create a type of GenericRepository<objectType>
Type refObjectRepositoryType = typeof(GenericRepository<>).MakeGenericType(refObjectType);
// Create an instance of GenericRepository<objectType>
dynamic refObjectRepository = Activator.CreateInstance(refObjectRepositoryType);
// Fill the dynamic POCO instance with the values of the referenced POCO instance
refObject = refObjectRepository._context.Entry(poco).Reference(refObjectType.Name).CurrentValue;
try
{
// Set the dto property with the name value of the referenced POCO instance
// (i.e. dtoImage.ImageType = pocImage.ImageType.Name)
pf.SetValue(dto, refObject.Name, null);
}
catch (RuntimeBinderException)
{
// this happens when the related entity is null, ie. in one to zero-or-one relationships
continue;
}
continue;
}
// If the propertyinfo's propertytype does not have an Id property, just set the value of
// the dto property to that of the POCO's propertyinfo directly
pf.SetValue(dto, pi.GetValue(poco, null), null);
}
}
现在,此代码仅适用于同时具有Id和Name属性的引用实体。此外,这种方法可能会有性能损失,因此我实现了标记includeRelated来切换是否查询相关对象。
答案 0 :(得分:1)
您尝试从父PropertyInfo
获取价值,但GetValue
期望pi.PropertyType
类型的对象。你应该使用这样的东西:
using (var context = new MyContext())
{
var cust = context.Customer.First();
var custType = cust.CustomerType;
var pi = typeof (Customer).GetProperty("CustomerType");
var child = pi.PropertyType.GetProperty("CustomerTypeID");
var res = child.GetValue(custType, null);
// this returns value of Customer.CustomerTypeID
}