在运行时分配类属性

时间:2012-09-25 16:37:15

标签: c# winforms

我们说我有一个Order类,它具有OrderName,OrderNum等属性......

然后使用此类中的项目列表填充ComboBox,让我说我这样做:

comboBox1.DisplayMember = "OrderName";
comboBox1.ValueMember = "OrderNum";
comboBox1.DataSource = list.ToArray<Order>();

所以在这里我很难编码代码中的那些字段的名称,例如&#34; OrderName&#34;。有没有更好的方法来做这个而不是硬编码字段的名称?它需要某种依赖注入技巧吗?你有什么建议?

4 个答案:

答案 0 :(得分:3)

如果可能,您可以按照@JesseCSlicer提到的那样继续,但如果您无法更改业务类,那么您可以采用这种方法:

基于此SO answer,我们可以编写自己的帮助器:

public static class PropHelper<T>
{
    public static string PropName<R>(Expression<Func<T,R>> exp)
    {
        var mem = exp.Body as MemberExpression;
        if(mem != null) return mem.Member.Name;     
        throw new ArgumentException("Invlaid Property Name");
    }
}

并使用它:

comboBox1.DisplayMember = PropHelper<Order>.PropName(o => o.OrderName);
comboBox1.ValueMember = PropHelper<Order>.PropName(o => o.OrderNum);
comboBox1.DataSource = list.ToArray<Order>();

答案 1 :(得分:2)

下面是我在几个ASP.NET应用程序中使用的修改过的类。我在你的样本中分配它的方式是这样的:

var orders = model.GetOrders(...);

comboBox1.DisplayMember = OrderQueryResults.DisplayMember;
comboBox1.ValueMember = OrderQueryResults.ValueMember;
comboBox1.DataSource = orders.Results;

类别:

public sealed class OrderQueryResults : IOrderQueryResults
{
    private const string DisplayName = "OrderName";

    private const string ValueName = "OrderNum";

    private readonly IEnumerable<IOrderQueryResult> results;

    private readonly object extra;

    private OrderQueryResults(IEnumerable<IOrderQueryResult> results, object extra)
    {
        this.results = results;
        this.extra = extra;
    }

    public string DisplayMember
    {
        get
        {
            return DisplayName;
        }
    }

    public string ValueMember
    {
        get
        {
            return ValueName;
        }
    }

    public IEnumerable<IOrderQueryResult> Results
    {
        get
        {
            return this.results;
        }
    }

    public object Extra
    {
        get
        {
            return this.extra;
        }
    }

    public static IOrderQueryResults Create(IEnumerable<IOrderQueryResult> results, object extra)
    {
        if (results == null)
        {
            throw new ArgumentNullException("results");
        }

        return new OrderQueryResults(results.ToList(), extra);
    }
}

答案 2 :(得分:2)

这些只是Order的属性,对吧?所以你可以使用const - 这比代码中的文字要好得多 - 但如果你愿意,你当然可以在运行时更改它们。你只需要知道它们是什么。

在您的类中,“OrderName”和“OrderNum”只是表示属性名称的字符串,因此如果您的Order类中碰巧有其他属性,则可以获取这些属性的名称和例如,从某些用户操作中分配它们。

如果您愿意,可以使用反射来检查Order类。类似的东西:

Type theType =(typeof(Order));
// Get the public properties.
PropertyInfo[] thePropertyInfo =
    theType.GetProperties(BindingFlags.Public|BindingFlags.Instance);

要获取该PropertyInfo数组中任何特定属性的名称,您可以这样:

thePropertyInfo[i].Name;

会给你对象中第i个属性的名称。

那么,你可以说,将这些属性放入某个列表中,该列表本身绑定到控件 - 如ComboBox,然后在运行时选择DisplayMember和{{1}将被使用,然后只需设置它们,绑定将自动更新。

答案 3 :(得分:0)

最好使用置于Order类中的const字符串,并在绑定数据源时随处使用这些常量。