来自 TempData 的 TypeCast 列表 <T>

TypeCast List<T> from TempData

我正在尝试创建一个 MVC 视图来为我的搜索结果显示一个 "Details" 页面,它可以是许多不同的类型(应用程序、人员、计算机、许可证等)...

考虑到所有这些不同的类型都没有相同的对象属性,甚至没有相同的基本属性,我决定处理这个问题的方法是在搜索视图中传递结果列表,到细节控制器。

但是,我在控制器中读取该信息时遇到问题...这是我目前拥有的代码(部分):

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. 然后,通过列表中的第一个元素将其类型转换为真实类型...

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

所以我的问题有两个:

  1. 按这个顺序我的逻辑合理吗?
  2. 还有其他 way/standard 方法吗?

You cannot cast a List<T> to a List<object>(除非Tobject)。您可以转换为 IEnumerable<object> 并更改 "first" 对象提取:

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

...

object TypeUse = SearchResults.First();

这是由于 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> 类型或什至是一个基础 interface/class,您的所有可搜索类型都继承自该类型,从而允许您使用任何公共属性按照你的逻辑。

跟进

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