4

次のことを達成するために、式ツリーと匿名型を使用しようとしています。

このクラスがあるとしましょう:

class Person
{
   public string FirstName {get;set;}
   public string MiddleName {get;set;}
   public string LastName {get;set;}
   public DateTime DateOfBirth {get;set;}
}

今、私は以下を呼び出すことができるようにしたい:

string[] names = Foo<Person>(x=> new { x.LastName, x.DateOfBirth });

名前に「LastName」と「DateOfBirth」の 2 つの項目を含めたい。

すべてを選択するのではなく、SQL に含めたいプロパティ/列のリストを指定できるように、文字列 sql を記述するのではなく、コンパイル時に安全な方法でPetaPocoを拡張しようとしています。非常に大きなエンティティがいくつかあり、パフォーマンス上の理由からすべての列を選択したくない場合があります。

4

5 に答える 5

3

サイズについてこれを試してください:

public static string[] Foo<T, TResult>(Expression<Func<T, TResult>> func)
{
    return typeof(TResult).GetProperties().Select(pi => pi.Name).ToArray();
}

ラムダから匿名型を返しているので、この匿名型のすべてのプロパティをループして、プロパティの推測された名前を使用できます。ただし、これを使用する場合、構文は次のようになります。

Foo((Person x) => new { x.LastName, x.DateOfBirth });

これは、2 番目のジェネリック引数が無名型であるためです。

于 2012-03-28T22:28:48.433 に答える
2

私は怠け者なので、このコードはパブリック プロパティのみを処理します。しかし、それはあなたが始めるための良いベースになるはずです.

public static string[] Foo<T>(Expression<Func<T, object>> func)
{
    var properties = func.Body.Type.GetProperties();

    return typeof(T).GetProperties()
        .Where(p => properties.Any(x => p.Name == x.Name))
        .Select(p =>
        {
            var attr = (ColumnAttribute) p.GetCustomAttributes(typeof(ColumnAttribute), true).FirstOrDefault();
            return (attr != null ? attr.Name : p.Name);
        }).ToArray();
}
于 2012-03-28T22:24:50.553 に答える
0

コードのページは 1,000 語なので、Microsoft がPrismでそれを行う方法は次のとおりです。

///<summary>
/// Provides support for extracting property information based on a property expression.
///</summary>
public static class PropertySupport
{
    /// <summary>
    /// Extracts the property name from a property expression.
    /// </summary>
    /// <typeparam name="T">The object type containing the property specified in the expression.</typeparam>
    /// <param name="propertyExpression">The property expression (e.g. p => p.PropertyName)</param>
    /// <returns>The name of the property.</returns>
    /// <exception cref="ArgumentNullException">Thrown if the <paramref name="propertyExpression"/> is null.</exception>
    /// <exception cref="ArgumentException">Thrown when the expression is:<br/>
    ///     Not a <see cref="MemberExpression"/><br/>
    ///     The <see cref="MemberExpression"/> does not represent a property.<br/>
    ///     Or, the property is static.
    /// </exception>
    public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
    {
        if (propertyExpression == null)
        {
            throw new ArgumentNullException("propertyExpression");
        }

        var memberExpression = propertyExpression.Body as MemberExpression;
        if (memberExpression == null)
        {
            throw new ArgumentException(Resources.PropertySupport_NotMemberAccessExpression_Exception, "propertyExpression");
        }

        var property = memberExpression.Member as PropertyInfo;
        if (property == null)
        {
            throw new ArgumentException(Resources.PropertySupport_ExpressionNotProperty_Exception, "propertyExpression");
        }

        var getMethod = property.GetGetMethod(true);
        if (getMethod.IsStatic)
        {
            throw new ArgumentException(Resources.PropertySupport_StaticExpression_Exception, "propertyExpression");
        }

        return memberExpression.Member.Name;
    }
}

属性を考慮に入れたい場合は、もう少し複雑になりますが、 を受け入れExpression<Func<T>>て対象となるプロパティの名前を釣り上げるという一般的な考え方は同じです。

更新:そのままでは、メソッドは 1 つのパラメーターのみを受け入れます。私はそれをガイドラインとして提供しただけです。もちろん、アイデアは一般化できます。

public static string[] ExtractPropertyNames<T>(
    Expression<Func<T, object>> propertyExpression)

このメソッドは、T を受け取る式を受け入れ、後で反映できる匿名型を返します。2 番目の型パラメーターを置き換えることもできますがobject、ここでは何もしません。なぜなら、やりたいことは型を反映することだけだからです。

于 2012-03-28T22:16:39.797 に答える
-1

Html.LabelFor(LabelExtensions.LabelFor<TModel,TValue>アセンブリからコードを逆アセンブルする必要があると思いますSystem.Web.Mvc)。

たとえば、ExpressionHelper.GetExpressionText

メンバー名を属性メンバー値に置き換える場合は、昔ながらのリフレクションを使用する必要があります。

于 2012-03-28T22:17:52.620 に答える