Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在运行时将通过反射获取的属性强制转换为正确的泛型类型_C#_Entity Framework_Asp.net Core_.net Core_Reflection - Fatal编程技术网

C# 如何在运行时将通过反射获取的属性强制转换为正确的泛型类型

C# 如何在运行时将通过反射获取的属性强制转换为正确的泛型类型,c#,entity-framework,asp.net-core,.net-core,reflection,C#,Entity Framework,Asp.net Core,.net Core,Reflection,简而言之,我要实现的是根据配置验证我(ef core)DbContext中的特定DbSets。这意味着我希望在配置中指定要验证的表,然后我将对我的DbContext中匹配的DbSet应用验证规则。请允许我解释: 假设配置中有以下值作为JSON数组: "TablesToValidate" : [ "Appointments", "Products" ] 这些值映射到以下各项: public class AppSettin

简而言之,我要实现的是根据配置验证我(ef core)
DbContext
中的特定
DbSet
s。这意味着我希望在配置中指定要验证的表,然后我将对我的
DbContext
中匹配的
DbSet
应用验证规则。请允许我解释:

假设配置中有以下值作为JSON数组:

"TablesToValidate" : [
    "Appointments",
    "Products"
]
这些值映射到以下各项:

public class AppSettings {
    public IEnumerable<DatabaseTable> TablesToValidate { get; set; }
}
下面是DbContext的简化版本:

public DbContext(....)
{
    DbSet<Appointment> Appointments { get; set; }
    DbSet<Product> Products { get; set; }
    DbSet<User> Users { get; set; }
}
正如您所看到的,我想在获取的
DbSet上执行的操作是检查它是否为null(如果我将它转换为
对象
),以及
DbSet.Any()
,这是主要问题

无论我采取什么方法,我仍然需要DbSet的实际泛型类型,以便能够调用
DbSet
变量上的
Any()
函数。 我无法将运行时类型放入泛型定义
,因为它需要编译时类型。我还尝试将
dbSet
变量强制转换为
dbSet
,其中
BaseEntity
是所有
约会
产品
用户
的父项,但我怀疑它不起作用,并且会返回null,因为强制转换总是失败的


关于如何解决这个问题,有什么想法吗?

尝试转换为非泛型的
IEnumerable
。然后可以使用
foreach
查看它是否为空

var dbSet = propertyInfo.GetValue(dbContext) as IEnumerable;

bool isEmpty = true;
foreach (var item in dbSet) { isEmpty = false; break; }

您将无法强制转换为“unknown generic”,然后将其作为参数传递给函数。但您可以通过反射调用带有匹配参数的泛型函数。不过看起来不太好看

//首先,我们构造参数的泛型类型,该参数指向AnyAsync。
//myType是给定数据库集的实体类型。
var参数type=typeof(IQueryable)。MakeGenericType(myType);
//其次,我们从EF扩展中提取所需的方法。
//确保得到正确的重载,我们需要一个没有谓词的重载。
var methodInfo=typeof(EntityFrameworkQueryableExtensions)
.GetMethod(名称(EntityFrameworkQueryableExtensions.AnyAsync),
1.
新[]{parameterType,typeof(System.Threading.CancellationToken)})
.MakeGenericMethod(myType);
//使用非类型化参数调用该方法
var结果=等待(任务)方法信息
.Invoke(空,
新对象[]{dbSet,默认值(System.Threading.CancellationToken)});

这是个糟糕的主意。直接从DbSet获取枚举数将导致加载整个表。
appSettings
    .TablesToValidate
    .ToList()
    .Foreach(table => {
        var propertyInfo = dbContext //an instance of the DbContext
                        .GetType()
                        .GetProperty(table.ToString());

        // let's say propertyInfo is not null

        var dbSet = propertyInfo.GetValue(dbContext) as DbSet<?>; //Consider this line
        
        if (dbSet is null || !dbSet.Any())
        {
            //db set not valid. Do Something
        }
    });
var dbSet = propertyInfo.GetValue(dbContext) as IEnumerable;

bool isEmpty = true;
foreach (var item in dbSet) { isEmpty = false; break; }