来自TempData的TypeCast List <t> </t>

时间:2015-03-23 16:18:07

标签: c# asp.net-mvc-4

我正在尝试创建一个单独的MVC视图来显示&#34;详细信息&#34;我的搜索结果页面,可以有多种不同类型(应用程序,人员,计算机,许可证等)...

鉴于所有这些不同的类型都没有相同的对象属性,甚至是相同的基本属性,我决定要做的就是在搜索视图中传递结果列表,到细节控制器。

但是,我在控制器内读回信息时遇到了问题......这是我到目前为止的代码(部分):

public ActionResult Details(int index)
    {
        List<object> SearchResults = TempData.ContainsKey("SearchItems") ? TempData["SearchItems"] as List<object> : null;
        if(SearchResults == null)
        {
            //go to error page.
            ViewBag.ErrorDescription = "Oups! Something went wrong trying to load the profile information. If you continue to see this error message, please contact the system administrator with the details below.";
            ViewBag.ErrorMessage = "An internal error occurred: TempData object key not found.";
            return View("Error");
        }

        if(SearchResults.Count == 0)
        {
            //go to error page.
            ViewBag.ErrorDescription = "Oups! Something went wrong trying to load the profile information. If you continue to see this error message, please contact the system administrator with the details below.";
            ViewBag.ErrorMessage = "An internal error occurred: TempData object contains no elements.";
            return View("Error");
        }

        //I also check if the index is out of range and stuff... 

        object TypeUse = SearchResults[0];

         //case statement and other actions are here...

    }

到目前为止,我可以通过在调试器中查找TempData[SearchItems]来查看列表,它会在我尝试强制转换为List<object>时显示正确的信息,但是出于某种原因, SearchResults变为空。

正如您在上面的代码中所看到的,我遵循的逻辑是:

  1. 检查列表是否存在;
  2. 检查它是否为空;
  3. 其他检查;和
  4. 只有这样,通过列表中的第一个元素将其强制转换为真正的类型......

  5. 从那里我将在视图中显示此类对象的正确信息......

    所以我的问题有两个方面:

    1. 按此顺序执行此操作是否符合我的逻辑?
    2. 还有另一种方法/标准方法吗?

2 个答案:

答案 0 :(得分:3)

You cannot cast a List<T> to a List<object>(除非T object)。您可以转换为IEnumerable<object>并更改您的第一个&#34;对象提取:

IEnumerable<object> SearchResults = 
    TempData.ContainsKey("SearchItems") ? 
        TempData["SearchItems"] as IEnumerable<object> : 
        null;

...

object TypeUse = SearchResults.First();

答案 1 :(得分:2)

这是由于co variance and contra variance

CatDog都从Animal继承。

您可能希望能够将List<Cat>转换为List<Animal>,例如

List<Cat> cats = new List<Cat>();
cats.Add(new Cat());
List<Animal> animals = (List<Animal>)cats;

Animal first = animals[0];

现在虽然看起来都很好,此代码实际上无法正常工作,如果实际允许此行为,那么您将如何应对

animals.Add(new Dog());

Dog不是要存储到List<Cat>的有效类型。

由于您想要提取基本类型的集合,您可以使用IEnumerable<Animal>

IEnumerable<Animal> animals = (IEnumerable<Animal>)cats;
Animal first = cats.First(); // using Linq;

请注意,出于类似的原因,您不能直接转回IEnumerable<Cat>,因为并非每个Animal都是Cat。您可以使用Linq扩展方法OfType<Cat>()Cast<Cat>()来执行此操作。

因此,在您的情况下,您需要SearchResultsIEnumerable<object>类型,或者甚至是所有可搜索类型继承的基本接口/类,允许您使用逻辑中的任何公共属性。

<强>后续

如果您使用的是.Net 4.5,则可以使用IReadonlyList<T>代替IEnumerable<T>。这提供了仍然提供计数和项目索引的额外优点。