0

Expression<Func<T, TValue>>(like m => m.Name) とが与えられた場合index、式を ) に変換できるようにしたいと考えていますm => m[index].Name。そして、私は立ち往生していることを認めなければなりません...

「一体なぜ」が必要な場合は、実際のシナリオを提供します(そして、より良い方法を見つけるかもしれません)。

シナリオ:サーバー側の編集可能グリッド( javascript なし) を想像してください。

次のようなヘルパーを使用してグリッドを構築します。

@(Html.Grid(Model)
.Columns(columns => {
   columns.Edit(m => m.Name);
   columns.Edit(m => m.Code);
})
.AsEditable());

モデルはIQueryable<T>

m => m.NameExpression<Func<T, TValue>>(はTValue文字列) です

m => m.CodeExpression<Func<T, TValue>>( TValueint です)

ビューをレンダリングするときに、html フォームを表示したいと思います。IQueryable<T>が列挙されます (順序、ページ付け) 。=>わかりました

したがって、5、10 List<T>、または 20 個のTアイテムがあります。

とは、クラシックを使用してとして表す必要がありますName( を作成しても問題ありません) 。CodeTextBoxHtmlHelper.TextBoxFor(Expression<Func<T, TValue>>)HtmlHelper<T>

しかし、私はリストを持っているので、正しいモデルバインディングm => m.Nameが必要な場合は、直接使用することはできませんが、使用する必要がありますm => m[indexOfItem in List<T>].Name

編集:詳細:

エンティティクラスがあるとしましょう

public class Test {
  public int Id {get;set;}
  public string Name {get;set;}
  public string Code {get;set;}
}

次に、IQueryable<Test>

次に、ビュー

@model IQueryable<Test>

@(Html.Grid(Model)
    .Columns(columns => {
       columns.Edit(m => m.Name);
       columns.Edit(m => m.Code);
    })
    .AsEditable());

ご覧のとおり、パラメータとして指定されたモデルはIQueryable<Test>です。

m => m.Name

m => m.Code

モデルの単なるプロパティです(グリッドに TextBox として表示したい)。

グリッドが順序付けとページ付けを管理するため、モデルはIQueryable<T>(ではなく) であり、コントローラーとサービス レイヤーはページ付けと順序付けについて知る必要がありません。IEnumerable<T>

より明確ですか?

4

2 に答える 2

1

This could be easily achieved by writing a custom ExpressionVisitor:

public static class ExpressionExtensions
{
    private class Visitor : ExpressionVisitor
    {
        private readonly int _index;
        public Visitor(int index)
        {
            _index = index;
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            return Expression.ArrayIndex(GetArrayParameter(node), Expression.Constant(_index));
        }

        public ParameterExpression GetArrayParameter(ParameterExpression parameter)
        {
            var arrayType = parameter.Type.MakeArrayType();
            return Expression.Parameter(arrayType, parameter.Name);
        }
    }

    public static Expression<Func<T[], TValue>> BuildArrayFromExpression<T, TValue>(
        this Expression<Func<T, TValue>> expression,
        int index
    )
    {
        var visitor = new Visitor(index);
        var nexExpression = visitor.Visit(expression.Body);
        var parameter = visitor.GetArrayParameter(expression.Parameters.Single());
        return Expression.Lambda<Func<T[], TValue>>(nexExpression, parameter);
    }
}

and then you could use this extension method like this:

Expression<Func<Test, string>> ex = m => m.Code;
Expression<Func<Test[], string>> newEx = ex.BuildArrayFromExpression(1);
于 2012-11-19T17:15:50.737 に答える
0

さて、何か(醜い、テスト目的のためだけに)動作しましたが、それは物事を不明確にするので、より良い解決策を待つか、別の方法で入力を構築します:

public static Expression<Func<T[], TValue>> BuildArrayFromExpression<T, TValue>(this Expression<Func<T, TValue>> expression, int index)
{
    var parameter = Expression.Parameter(typeof(T[]), "m");
    Expression body = Expression.ArrayIndex(parameter, Expression.Constant(index));
    var type = typeof(T);
    var properties = expression.Body.ToString().Split('.');//ugly shortcut for test only
    foreach (var property in properties.Skip(1))
    {
        var pi = type.GetProperty(property);
        body = Expression.Property(body, type.GetProperty(property));
        type = pi.PropertyType;
    }
    return Expression.Lambda<Func<T[], TValue>>(body, parameter);
}

my の各行に対して呼び出される RenderMethod で使用されますList<T>( my から返されたページ分割された/順序付きリストIQueryable<T>)

public override ... RenderContent(T dataItem) {
  var helper = new HtmlHelper<T[]>(GridModel.Context, new GridViewDataContainer<T[]>(GridModel.PaginatedItems.ToArray(), GridModel.Context.ViewData));
  var modifiedExpression = Expression.BuildArrayFromExpression(GridModel.PaginatedItems.IndexOf(dataItem));//GridModel.PaginatedItems is the List<T> returned when "executing" the IQueryable<T>
  var textBox = helper.TextBoxFor(modifiedExpression);
  ...
}
于 2012-11-19T13:49:46.157 に答える