【问题标题】:How to traversal Generic object properties in c#如何在c#中遍历通用对象属性
【发布时间】:2017-10-21 15:11:46
【问题描述】:

问题是我经常遇到一个场景,在方法调用的时候需要遍历实例对象的属性作为另一个对象方法传入参数。如下:

//Step 1
var criteria =new Criteria();
SqlCommand cmd =SqlCommandManager.GetDataCommand("SearchOrderList");
//Step 2
//The define of the SetParameterValue method is :
//public void SetParameterValue(string paramName, object val);
cmd.SetParameterValue("@SellerID",criteria.SellerID );
cmd.SetParameterValue("@DateFrom", criteria.SentDateFrom);
cmd.SetParameterValue("@DateTo", criteria.SentDateTo);
cmd.SetParameterValue("@StartRowIndex", criteria.PagingInfo.StartRowIndex);
cmd.SetParameterValue("@PageSize", criteria.PagingInfo.PageSize);
cmd.SetParameterValue("@SortField", criteria.PagingInfo.SortField);
cmd.SetParameterValue("@SortType", criteria.PagingInfo.SortType);
//cmd.SetPa........
//Step 3
cmd.ExecuteEntityList<Model>();

我如何制定一种灵活且可扩展的方法来简化第 2 步。 我有一个想法是制作一个通用方法来处理这个:

public static void SetParameterValues<T>(this DataCommand cmd,T _object)
    {
        if (Object.ReferenceEquals(cmd,null))
            throw new ArgumentException("The Parameter cmd must be not null", "cmd");
        if (!object.ReferenceEquals(_object, null))
        {
            //to do ...
        }

    }

但我对下一步应该继续处理什么感到困惑(我已经做了一个扩展方法)。 那你们能帮我看看这个问题吗?

【问题讨论】:

  • 如果您尝试这样做是为了在 SQL 数据库中执行命令,那么这基本上是一个已解决的问题 - 请阅读 Entity Framework 或 nHibernate 等 ORM。
  • Generics 在这里根本帮不了你。做到这一点的方法,如果你真的想概括(为什么有人猜测),将通过反射,但你需要一些自定义属性支持来知道你真正需要添加哪些属性(如果所有公共属性都受制于是参数,那么你就不需要它了)。在任何情况下,您的 Tobject 一样“无用”,因此请选择后者,不要让您的方法看起来像是在做一些实际上并没有做的事情。
  • 这就是我要做的,但我不知道如何构建它。在我完成遍历属性后,我可能会使用属性(或其他)来推断需要遍历的属性。

标签: c# .net generics backend


【解决方案1】:

不要让一种方法通用,然后以某种方式区分不同的类型,而是创建方法的重载版本

public static void SetParameterValue(this DataCommand cmd, string parameter, int value)
public static void SetParameterValue(this DataCommand cmd, string parameter, string value)
public static void SetParameterValue(this DataCommand cmd, string parameter, DateTime value)
...

例如

public static void SetParameterValue(this DataCommand cmd, string parameter, int value)
{
    if (Object.ReferenceEquals(cmd,null))
        throw new ArgumentException("The Parameter cmd must be not null", "cmd");
    cmd.Parameters.Add(parameter, SqlDbType.Int).Value = value;
}

但是如果你想推断参数名称,你将不得不使用另一种方法。为了能够访问属性名称,您需要一个表达式树:

public static void SetParameterValue<T>(this DataCommand cmd, Expression<Func<T>> expr)
{
    var member = expr.Body as MemberExpression;
    if (member == null)
        throw new ArgumentException("We need a member expression of type obj.PropertyName");

    var prop = member.Member as PropertyInfo;
    if (prop == null)
        throw new ArgumentException("We need a property, not a field");

    string name = prop.Name;
    T value = expr.Compile()();

    cmd.Parameters.AddWithValue("@" + name, value);
}

然后您必须使用 lambda 表达式调用它

cmd.SetParameterValue(() => criteria.SellerID); 

【讨论】:

  • ...或者使用众多 ORM 框架中的一种,它们会为您执行此操作
猜你喜欢
  • 2018-12-19
  • 2016-09-09
  • 2012-01-08
  • 2016-05-12
  • 2019-10-19
  • 2021-08-28
  • 1970-01-01
相关资源
最近更新 更多