IList <variableType>; Решить без дженериков - PullRequest
1 голос
/ 03 августа 2009

Я нашел много похожих вопросов, но ничего не дал ответ. Частично моя проблема связана с невозможностью использовать Generics в атрибутах.

Я, вероятно, пытаюсь слишком усложнить ситуацию, поэтому, если вы можете придумать более простой способ сделать это, я весь в ушах.

Моя конкретная проблема связана с ASP.NET MVC, использующим атрибуты (фильтры) в методе Action. Я пытаюсь создать фильтр, который разбивает на страницы результаты, переданные ViewData.Model, следующим образом:

[PagedList(PageSize = 2, ListType = typeof(Invoice))]
public ViewResult List()
{
    var invoices = invoicesRepository.Invoices; // Returns an IQueryable<Invoice>
    return View(Invoices);
}

Переопределение моего фильтра OnActionExecuted затем выглядит следующим образом:

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
    ViewResult result = (ViewResult)filterContext.Result;
    var list = (IQueryable<?>)result.ViewData.Model; // Here I want to use the ListType in place of the ?

    // Perform pagination
    result.ViewData.Model = list.Skip((Page - 1) * PageSize).Take(PageSize.ToList();
}

Я понимаю, что могу заменить свой

var list = (IQueryable<?>)result.ViewData.Model;

С

var list = (IQueryable)result.ViewData.Model;
IQueryable<Object> oList = list.Cast<Object>();

Но мой взгляд строго типичен, чтобы ожидать

IQueryable<Invoice>

не

IQueryable<Object>

Ответы [ 3 ]

4 голосов
/ 03 августа 2009

Не могли бы вы потенциально создать универсальный метод в своем фильтре, который делает то, что вам нужно, а затем в OnActionExecuted использовать рефлексию для вызова этого универсального метода с ListType?


РЕДАКТИРОВАТЬ: Например, вы бы создать новый метод с этой подписью:

private void GenericOnActionExecuted<T>( ActionExecutedContext filterContext )

Этот метод будет иметь тот же код, что и вы. Тогда вы бы переписали OnActionExecuted так:

public void OnActionExecuted( ActionExecutedContext filterContext )
{
    MethodInfo genericMethod =
        GetType().GetMethod( "GenericOnActionExecuted",
            BindingFlags.Instance | BindingFlags.NonPublic );

    MethodInfo constructedMethod = genericMethod.MakeGenericMethod( ListType );

    constructedMethod.Invoke( this, new object[] { filterContext } );
}
1 голос
/ 03 августа 2009

Я никогда не использовал ASP.NET MVC, но, исходя из вашего объяснения, я бы сказал, что у вас есть два варианта. Оба эти решения требуют, чтобы вы добавили универсальную версию OnActionExecuted к вашему атрибуту.

protected void DoActionExecuted<T>(ActionExecutedContext filterContext)
{
    var result = (ViewResult) filterContext.Result;
    var list = (IQueryable<T>) result.ViewData.Model;
    result.ViewData.Model = list.Skip((Page - 1)*PageSize)
                                .Take(PageSize)
                                .ToList();
}

Вы можете использовать отражение для вызова метода с параметром динамического типа:

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
    GetType().GetMethod("DoActionExecuted",
                        BindingFlags.NonPublic | BindingFlags.Instance)
             .MakeGenericMethod(ListType)
             .Invoke(this, new[] {filterContext});
}

Или вы можете создать подкласс закрытого атрибута, который знает об универсальном типе во время компиляции:

[PagedInvoiceList(PageSize = 2, ListType = typeof (Invoice))]
public ViewResult List() { ... }

private class PagedInvoiceListAttribute : PagedListAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        DoActionExecuted<Invoice>(filterContext);
    }
}
0 голосов
/ 03 августа 2009

Из того, что я смог выяснить, это варьируется от трудного до невозможного, когда вы пытаетесь достичь этого.

Если я правильно понимаю ваш вопрос, вы хотите сделать что-то вроде этого:

  var someGenericResult = (IQueryable<typeof(SomeType)>)result.ViewData.Model;

Вы можете попытаться использовать информацию здесь , но я не знаю, поможет ли она вам в вашем конкретном случае, поскольку вы используете интерфейсы для передачи информации - как и должно быть - и до сих пор существует проблема преобразования типов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...