调用泛型方法时使用 PropertyInfo 作为泛型类型
Use PropertyInfo as generic type when calling a generic method
背景
我正在使用 EF,并且我有很多表。当我插入一个具有导航属性内容但没有 id 的新实体时(我正在从 xls 文件中读取内容)我不想显式加载所有导航属性。这是太多的代码。所以我尝试了一种通用的方式:
private void loadExistingNavigationProperties<TEntity>(TEntity entityToInsert) where TEntity : class
{
Type type = typeof(TEntity);
var properties = type.GetProperties().Except(type.GetProperties().Where(x => x.Name.Contains("id")));
foreach (PropertyInfo property in properties)
{
if (property.PropertyType.FullName.Contains("MyNamespace"))
{
property.SetValue(entityToInsert, findNavigationProperty<???>(property.GetValue(entityToInsert)));
}
}
}
我有我的 entityToInsert
。如果它有导航 属性 (contains("MyNamespace")
),我会检查它的所有属性。如果这是真的,导航 属性 应该加载(见下文)并设置。
private object findNavigationProperty<TNavigationProperty>(TNavigationProperty navigationPropertyValue) where TNavigationProperty : class
{
List<TNavigationProperty> navigationProperties = GetAllEntries<TNavigationProperty>();
foreach (var entity in navigationProperties)
{
if (propertiesAreEqual(entity, navigationPropertyValue))
{
return entity;
}
}
return navigationPropertyValue;
}
导航 属性 属性的当前值已传递。它包含所有信息,例如名称或其他信息,但不包含 ID。首先,我获取所有具有该类型的可用导航属性。然后我正在搜索是否有一个 属性 与当前的具有相同的属性。然后返回这个并设置为导航属性.
编辑:
public List<TEntity> GetAllEntries<TEntity>() where TEntity : class
{
using (var dbContext = new InventarDBEntities(MainWindow.connectionName))
{
return GetAllEntries<TEntity>(dbContext);
}
}
public List<TEntity> GetAllEntries<TEntity>(InventarDBEntities dbContext) where TEntity : class
{
return dbContext.Set<TEntity>().ToList();
}
问题
我现在的问题是如何告诉方法 findNavigationProperty
通用类型是 属性 的值所具有的类型。所以用 type.
替换 ???
您可以像这样检索通用类型:
var item = propertyInfo.GetGenericArguments()[0];
可以使用"is"
检查是否是类型
您还可以这样做:
item.BaseType == typeof(Whatever type your navigation props inherit);
正如我在评论中提到的那样:
泛型类型参数在编译时解析。
因此,您无法从 System.Type
检索通用类型。
您的问题的关键是使用 System.Type
而不是泛型。
请注意,我没有测试下面的代码,因为我还没有安装 EF。
根据我的知识,DbContext 的 System.Type
重载应该可以正常工作。
private void loadExistingNavigationProperties<TEntity>(TEntity entityToInsert) where TEntity : class
{
Type tEntity = typeof(TEntity);
var properties = tEntity.GetProperties().Except(tEntity.GetProperties().Where(x => x.Name.Contains("id")));
foreach (PropertyInfo property in properties)
{
if (property.PropertyType.FullName.Contains("MyNamespace"))
{
object val = findNavigationProperty(property.GetValue(entityToInsert), tEntity);
property.SetValue(entityToInsert, val);
}
}
}
private object findNavigationProperty(object navigationPropertyValue, Type tEntity)
{
DbSet navigationProperties = GetAllEntries(tEntity);
foreach (var entity in navigationProperties)
{
// You may get a type issue.
// If so: cast to the correct type or change "propertiesAreEqual".
if (propertiesAreEqual(entity, navigationPropertyValue))
{
return entity;
}
}
return navigationPropertyValue;
}
public DbSet GetAllEntries(Type tEntity)
{
using (var dbContext = new InventarDBEntities(MainWindow.connectionName))
{
return GetAllEntries(dbContext, tEntity);
}
}
public DbSet GetAllEntries(InventarDBEntities dbContext, Type tEntity)
{
return dbContext.Set(tEntity);
}
背景
我正在使用 EF,并且我有很多表。当我插入一个具有导航属性内容但没有 id 的新实体时(我正在从 xls 文件中读取内容)我不想显式加载所有导航属性。这是太多的代码。所以我尝试了一种通用的方式:
private void loadExistingNavigationProperties<TEntity>(TEntity entityToInsert) where TEntity : class
{
Type type = typeof(TEntity);
var properties = type.GetProperties().Except(type.GetProperties().Where(x => x.Name.Contains("id")));
foreach (PropertyInfo property in properties)
{
if (property.PropertyType.FullName.Contains("MyNamespace"))
{
property.SetValue(entityToInsert, findNavigationProperty<???>(property.GetValue(entityToInsert)));
}
}
}
我有我的 entityToInsert
。如果它有导航 属性 (contains("MyNamespace")
),我会检查它的所有属性。如果这是真的,导航 属性 应该加载(见下文)并设置。
private object findNavigationProperty<TNavigationProperty>(TNavigationProperty navigationPropertyValue) where TNavigationProperty : class
{
List<TNavigationProperty> navigationProperties = GetAllEntries<TNavigationProperty>();
foreach (var entity in navigationProperties)
{
if (propertiesAreEqual(entity, navigationPropertyValue))
{
return entity;
}
}
return navigationPropertyValue;
}
导航 属性 属性的当前值已传递。它包含所有信息,例如名称或其他信息,但不包含 ID。首先,我获取所有具有该类型的可用导航属性。然后我正在搜索是否有一个 属性 与当前的具有相同的属性。然后返回这个并设置为导航属性.
编辑:
public List<TEntity> GetAllEntries<TEntity>() where TEntity : class
{
using (var dbContext = new InventarDBEntities(MainWindow.connectionName))
{
return GetAllEntries<TEntity>(dbContext);
}
}
public List<TEntity> GetAllEntries<TEntity>(InventarDBEntities dbContext) where TEntity : class
{
return dbContext.Set<TEntity>().ToList();
}
问题
我现在的问题是如何告诉方法 findNavigationProperty
通用类型是 属性 的值所具有的类型。所以用 type.
???
您可以像这样检索通用类型:
var item = propertyInfo.GetGenericArguments()[0];
可以使用"is"
检查是否是类型您还可以这样做:
item.BaseType == typeof(Whatever type your navigation props inherit);
正如我在评论中提到的那样:
泛型类型参数在编译时解析。
因此,您无法从 System.Type
检索通用类型。
您的问题的关键是使用 System.Type
而不是泛型。
请注意,我没有测试下面的代码,因为我还没有安装 EF。
根据我的知识,DbContext 的 System.Type
重载应该可以正常工作。
private void loadExistingNavigationProperties<TEntity>(TEntity entityToInsert) where TEntity : class
{
Type tEntity = typeof(TEntity);
var properties = tEntity.GetProperties().Except(tEntity.GetProperties().Where(x => x.Name.Contains("id")));
foreach (PropertyInfo property in properties)
{
if (property.PropertyType.FullName.Contains("MyNamespace"))
{
object val = findNavigationProperty(property.GetValue(entityToInsert), tEntity);
property.SetValue(entityToInsert, val);
}
}
}
private object findNavigationProperty(object navigationPropertyValue, Type tEntity)
{
DbSet navigationProperties = GetAllEntries(tEntity);
foreach (var entity in navigationProperties)
{
// You may get a type issue.
// If so: cast to the correct type or change "propertiesAreEqual".
if (propertiesAreEqual(entity, navigationPropertyValue))
{
return entity;
}
}
return navigationPropertyValue;
}
public DbSet GetAllEntries(Type tEntity)
{
using (var dbContext = new InventarDBEntities(MainWindow.connectionName))
{
return GetAllEntries(dbContext, tEntity);
}
}
public DbSet GetAllEntries(InventarDBEntities dbContext, Type tEntity)
{
return dbContext.Set(tEntity);
}