C# 如何对非泛型类型使用反射
我花了几个小时在这里寻找我的问题的答案,所以如果这是一个重复的查询,我很抱歉。如果是这样,请给我指出正确的方向。如果没有,请参见下文,我的任务如下: 创建一个函数,该函数可以动态地检查数据库,查看某个对象是否存在值 基本上,用户单击一个按钮,将项目移动到另一个阶段。在进入下一阶段之前,下一阶段可能有/可能没有要求。如果存在需求,则会向我发送两个数据点:C# 如何对非泛型类型使用反射,c#,linq,system.reflection,C#,Linq,System.reflection,我花了几个小时在这里寻找我的问题的答案,所以如果这是一个重复的查询,我很抱歉。如果是这样,请给我指出正确的方向。如果没有,请参见下文,我的任务如下: 创建一个函数,该函数可以动态地检查数据库,查看某个对象是否存在值 基本上,用户单击一个按钮,将项目移动到另一个阶段。在进入下一阶段之前,下一阶段可能有/可能没有要求。如果存在需求,则会向我发送两个数据点: ReflectionClass(字符串)[我将在此处使用DbSet字符串值或类字符串值] ReflectionProperty(字符串) 有
- ReflectionClass(字符串)[我将在此处使用DbSet字符串值或类字符串值]
- ReflectionProperty(字符串)
db.[DbSet].Any(w=>w.ID==PipelineID&&w.[ReflectionProperty]!=null)
或类似的内容
我尝试过使用ExpressionTrees,但无法使Func
与类型
变量一起工作。请参阅下面的代码,这将起作用,但我知道有一种更有效的方法可以使用反射来实现这一点,我只是不知道如何实现
public async Task<Feedback> vStageReqFields(Guid NextStageID, Guid PipelineID)
{
Feedback f = new Feedback();
bool Valid = true;
string InvalidList = string.Empty;
List<Domain.Pipeline.Pipeline> pipelines = new List<Domain.Pipeline.Pipeline>();
List<Domain.Pipeline.Billing> billings = new List<Domain.Pipeline.Billing>();
try
{
//Get a list of Validations needed before advancing Stage...
var validations = db.PipelineStageRequiredFields.Any(a=>a.StageID == NextStageID) ? db.PipelineStageRequiredFields.Where(w=>w.StageID == NextStageID).ToList() : null;
//If Validations exist, start validatiing...
if(validations != null && validations.Any())
{
Type objectType = (from asm in AppDomain.CurrentDomain.GetAssemblies()
from type in asm.GetTypes()
where type.IsClass && type.FullName == "Domain.Pipeline.Pipeline" // static class to find Assembly info, all v.ReflectionClasses come from the same Assembly...
select type).SingleOrDefault();
foreach (var v in validations)
{
if(Utility.HasProperty(objectType, v.RefelectionProperty))//Check to see if ReflectionsClass has ReflectionProperty
{
//Switch Statement for Reflection Class to Check Property Value...
switch (v.RefelectionClass)
{
case "Domain.Pipeline.Pipeline":
pipelines = GetAllMembers(db, "Pipelines").OfType<Domain.Pipeline.Pipeline>().Where(w => w.ID == PipelineID).ToList(); //Get all Pipeline Objects...
if (pipelines.Any())
{
var model = pipelines.FirstOrDefault();
var value = model.GetType().GetProperty(v.RefelectionProperty).GetValue(model, null); //Check if Required ReflectionProperty has a value...
if (value == null)
{
Valid = false;
if (string.IsNullOrEmpty(InvalidList))
{
InvalidList = "The following fields are required: " + v.RefelectionProperty;
}
else
{
InvalidList = InvalidList + ", " + v.RefelectionProperty;
}
}
}
else
{
f.Success = false;
f.Type = FeedbackType.Error;
f.SuccessMsg = "Error: Could not find a Pipeline with this ID: '" + PipelineID.ToString() + "'";
}
break;
case "Domain.Pipeline.Billing":
billings = GetAllMembers(db, "Billings").OfType<Domain.Pipeline.Billing>().Where(w => w.PipelineID == PipelineID).OrderByDescending(o => o.EffectiveDate).ToList();
if (billings.Any())
{
var model = billings.FirstOrDefault();
var value = model.GetType().GetProperty(v.RefelectionProperty).GetValue(model, null);
if (value == null)
{
Valid = false;
if (string.IsNullOrEmpty(InvalidList))
{
InvalidList = "The following fields are required: " + v.RefelectionProperty;
}
else
{
InvalidList = InvalidList + ", " + v.RefelectionProperty;
}
}
}
else
{
f.Success = false;
f.Type = FeedbackType.Error;
f.SuccessMsg = "Error: Could not find a Pipeline with this ID: '" + PipelineID.ToString() + "'";
}
break;
default:
f.Success = false;
f.Type = FeedbackType.Error;
f.SuccessMsg = "Error: Could not find any Data in the " + v.RefelectionClass + " table for this Pipeline: '" + PipelineID.ToString() + "'";
break;
}
}
else
{
f.Success = false;
f.Type = FeedbackType.Error;
f.SuccessMsg = "The " + v.RefelectionClass + " does not have a Property of " + v.RefelectionProperty;
}
}
}
//No Validations Exist, User can proceed...
else
{
f.Success = true;
f.Type = FeedbackType.Success;
f.SuccessMsg = "Success! There are no required fields for the next stage.";
}
}
catch(Exception ex)
{
f.Success = false;
f.Type = FeedbackType.Error;
f.SuccessMsg = ITool.GetExceptionDetails(ex);
}
return f;
}
考虑以下重构以删除重复的代码,并使其更加枯燥(不要重复您自己) 其中可以构建表达式以检查必填字段是否具有值
private Delegate buildRequiredFieldCheckDelegate(Type type, PropertyInfo propertyInfo) {
//Func<T, bool>
var delegateType = typeof(Func<,>).MakeGenericType(type, typeof(bool));
var prpertyDefaultValue = getDefaultValue(propertyInfo.PropertyType);
// p => p.Property != default(typeof(TProperty))
// p =>
var parameter = Expression.Parameter(type, "p");
// p => p.Property
var property = Expression.Property(parameter, propertyInfo);
// default(TProperty);
var defaultValue = Expression.Constant(prpertyDefaultValue);
// p => p.Property != default(TProperty)
var body = Expression.NotEqual(property, defaultValue);
// Func<T, bool> = T p => p.Property != default(TProperty)
var lambda = Expression.Lambda(delegateType, body, parameter);
return lambda.Compile();
}
private static object getDefaultValue(Type type) {
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
私有委托buildRequiredFieldCheckDelegate(类型类型,PropertyInfo PropertyInfo){
//Func
var delegateType=typeof(Func).MakeGenericType(type,typeof(bool));
var prpertyDefaultValue=getDefaultValue(propertyInfo.PropertyType);
//p=>p.Property!=默认值(typeof(TProperty))
//p=>
var参数=表达式参数(类型为“p”);
//p=>p.属性
var property=Expression.property(参数,propertyInfo);
//违约(TProperty);
var defaultValue=表达式常数(prpertyDefaultValue);
//p=>p.Property!=默认值(TProperty)
var body=Expression.NotEqual(属性,defaultValue);
//Func=tp=>p.Property!=默认值(TProperty)
var lambda=Expression.lambda(delegateType,body,parameter);
返回lambda.Compile();
}
私有静态对象getDefaultValue(类型){
return type.IsValueType?Activator.CreateInstance(类型):null;
}
考虑以下重构,以删除重复的代码并使其更加干燥(不要重复自己的代码)
其中可以构建表达式以检查必填字段是否具有值
private Delegate buildRequiredFieldCheckDelegate(Type type, PropertyInfo propertyInfo) {
//Func<T, bool>
var delegateType = typeof(Func<,>).MakeGenericType(type, typeof(bool));
var prpertyDefaultValue = getDefaultValue(propertyInfo.PropertyType);
// p => p.Property != default(typeof(TProperty))
// p =>
var parameter = Expression.Parameter(type, "p");
// p => p.Property
var property = Expression.Property(parameter, propertyInfo);
// default(TProperty);
var defaultValue = Expression.Constant(prpertyDefaultValue);
// p => p.Property != default(TProperty)
var body = Expression.NotEqual(property, defaultValue);
// Func<T, bool> = T p => p.Property != default(TProperty)
var lambda = Expression.Lambda(delegateType, body, parameter);
return lambda.Compile();
}
private static object getDefaultValue(Type type) {
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
私有委托buildRequiredFieldCheckDelegate(类型类型,PropertyInfo PropertyInfo){
//Func
var delegateType=typeof(Func).MakeGenericType(type,typeof(bool));
var prpertyDefaultValue=getDefaultValue(propertyInfo.PropertyType);
//p=>p.Property!=默认值(typeof(TProperty))
//p=>
var参数=表达式参数(类型为“p”);
//p=>p.属性
var property=Expression.property(参数,propertyInfo);
//违约(TProperty);
var defaultValue=表达式常数(prpertyDefaultValue);
//p=>p.Property!=默认值(TProperty)
var body=Expression.NotEqual(属性,defaultValue);
//Func=tp=>p.Property!=默认值(TProperty)
var lambda=Expression.lambda(delegateType,body,parameter);
返回lambda.Compile();
}
私有静态对象getDefaultValue(类型){
return type.IsValueType?Activator.CreateInstance(类型):null;
}
ReflectionClass变量可以引用数据库中5个表中的一个表
,但该开关仅适用于两个表?@Nkosi,是的,这是正确的。我把这两个案例陈述放进去,然后意识到一定有更简单的方法来完成这项任务,因此,它们只是暂时的。谢谢ReflectionClass变量可以引用数据库中5个表中的一个表
,但该开关仅适用于两个表?@Nkosi,是的,这是正确的。我把这两个案例陈述放进去,然后意识到一定有更简单的方法来完成这项任务,因此,它们只是暂时的。谢谢再次感谢,但我希望用一种动态方法来替换开关/案例,以实现相同的结果。对不起,我认为我在上述需求中没有那么具体。因此,我不必使用Switch/Case
,而是可以使用PropertyName
传递DbSet
或Class
,然后检查值,而不需要开关/Case
。这可行吗?@ColeLeffel我根据原始问题中提供的内容保留了开关。但是,应该有一些指标,表明您打算如何区分对不同数据的检索types@ColeLeffel特别是因为有不同的方式来获得所需的物品。你说得对。开关
需要保留,但只需要两种情况。主类型
(管道)和所有其他类型
(计费、计划、监督、作业设置等)。案例1:“管道”此类型
仅使用带有DbContext.[DbSet].Find(Guid)
方法的PipelineID参数。案例2:默认情况下,其他类型
(计费、日程安排、监督、作业设置等)需要PipelineID参数和OrderByDescending(o=>o.AddDate)
语句,然后在该语句中检索FirstOrDefault()
。在这两种情况下,我都需要再次检查属性值
,但我希望用实现相同结果的动态方法替换开关/案例
。对不起,我认为我在上述需求中没有那么具体。因此,我可以使用Pr传递DbSet
或类,而不是使用Switch/Case
private void validate(PipelineStageRequiredField field, Guid PipelineID, object model, List<string> required, List<string> errors) {
if (model != null) {
var propertyName = field.RefelectionProperty;
var objectType = model.GetType();
var propertyInfo = getProperty(objectType, propertyName);
if (propertyInfo != null) {
var isValidModel = buildRequiredFieldCheckDelegate(objectType, propertyInfo);
if (!(bool)isValidModel.DynamicInvoke(model)) {
required.Add(propertyInfo.Name);
}
} else {
errors.Add("The " + field.RefelectionClass + " does not have a Property of " + propertyName);
}
} else {
errors.Add("Error: Could not find a " + field.RefelectionClass + " with this Pipeline: '" + PipelineID.ToString() + "'");
}
}
private static PropertyInfo getProperty(Type type, string propertyName) {
return type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
}
private Delegate buildRequiredFieldCheckDelegate(Type type, PropertyInfo propertyInfo) {
//Func<T, bool>
var delegateType = typeof(Func<,>).MakeGenericType(type, typeof(bool));
var prpertyDefaultValue = getDefaultValue(propertyInfo.PropertyType);
// p => p.Property != default(typeof(TProperty))
// p =>
var parameter = Expression.Parameter(type, "p");
// p => p.Property
var property = Expression.Property(parameter, propertyInfo);
// default(TProperty);
var defaultValue = Expression.Constant(prpertyDefaultValue);
// p => p.Property != default(TProperty)
var body = Expression.NotEqual(property, defaultValue);
// Func<T, bool> = T p => p.Property != default(TProperty)
var lambda = Expression.Lambda(delegateType, body, parameter);
return lambda.Compile();
}
private static object getDefaultValue(Type type) {
return type.IsValueType ? Activator.CreateInstance(type) : null;
}