C# 如何对非泛型类型使用反射

C# 如何对非泛型类型使用反射,c#,linq,system.reflection,C#,Linq,System.reflection,我花了几个小时在这里寻找我的问题的答案,所以如果这是一个重复的查询,我很抱歉。如果是这样,请给我指出正确的方向。如果没有,请参见下文,我的任务如下: 创建一个函数,该函数可以动态地检查数据库,查看某个对象是否存在值 基本上,用户单击一个按钮,将项目移动到另一个阶段。在进入下一阶段之前,下一阶段可能有/可能没有要求。如果存在需求,则会向我发送两个数据点: ReflectionClass(字符串)[我将在此处使用DbSet字符串值或类字符串值] ReflectionProperty(字符串) 有

我花了几个小时在这里寻找我的问题的答案,所以如果这是一个重复的查询,我很抱歉。如果是这样,请给我指出正确的方向。如果没有,请参见下文,我的任务如下:

创建一个函数,该函数可以动态地检查数据库,查看某个对象是否存在值

基本上,用户单击一个按钮,将项目移动到另一个阶段。在进入下一阶段之前,下一阶段可能有/可能没有要求。如果存在需求,则会向我发送两个数据点:

  • ReflectionClass(字符串)[我将在此处使用DbSet字符串值或类字符串值]
  • ReflectionProperty(字符串)
有了这两段数据,我需要检查数据库(最好通过DbSet,使用LINQ或反射)

ReflectionClass变量可以引用数据库中5个表中的一个。因此,本质上,我需要一种方式来表示:
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;
}