代码之家  ›  专栏  ›  技术社区  ›  jeef3

ilist<variabletype>;无泛型求解

  •  1
  • jeef3  · 技术社区  · 16 年前

    我发现了许多类似的问题,但没有找到我想要的答案。我的部分问题是由于无法在属性中使用泛型。

    我可能想把事情弄得过于复杂,所以如果你能想出一个更简单的方法,我会全力以赴的。

    我的特定问题与ASP.NET MVC有关,它使用操作方法上的属性(过滤器)。我正在尝试创建一个筛选器,该筛选器将对传递给ViewData的结果进行分页。模型如下:

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

    我的过滤器 OnAction已执行 覆盖然后看起来像:

    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 回复  |  直到 16 年前
        1
  •  4
  •   Tinister    16 年前

    您是否可以在筛选器中创建一个执行所需操作的泛型方法,然后在 OnActionExecuted 使用反射调用具有 ListType ?


    编辑:例如,您将使用此签名创建一个新方法:

    private void GenericOnActionExecuted<T>( ActionExecutedContext filterContext )
    

    此方法的代码与您发布的代码相同。然后你会重写 OnAction已执行 像这样:

    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 } );
    }
    
        2
  •  1
  •   Nathan Baulch    16 年前

    我本人从未使用过ASP.NET MVC,但根据您的解释,我认为您有两种选择。这两种解决方案都要求您向属性中添加执行的OnAction的通用版本。

    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);
        }
    }
    
        3
  •  0
  •   Community Mohan Dere    9 年前

    从我所能理解的,这范围从困难到不可能,因为你试图实现它。

    如果我正确理解了你的问题,你就会想这样做:

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

    你可以尝试使用这些信息 here 但是,我不知道它是否会在您的特定情况下帮助您,因为您正在使用接口传递信息——正如您应该的那样——而且仍然存在类型转换的问题。