3

我有以下情况:

public JsonResult ChangeFilterList(int option)
{
    var data = new[] { new { Text = "Unknown option", Value = -1 } };
    switch (option)
    {
        case 2: data = _departmentnameRepository.All.Select(x => new { Text = x.DeptName, Value = x.Id }).ToArray();
            break;
        case 3: data = Session["projectid"] == null
                ? _assetSequenceRepository.All.Select(x => new { Text = x.AssetShotName, Value = x.Id }).ToArray()
                : _assetSequenceRepository.FindBy(p => p.ProjectId == (int)Session["projectid"]).Select(x => new { Text = x.AssetShotName, Value = x.Id }).ToArray();
            break;
        default: data = _userRepository.All.Select(x => new { Text = x.DisplayName, Value = x.UserID }).ToArray();
            break;
    }            

    return Json(data, JsonRequestBehavior.AllowGet);
}

case2看起来不错,default但抱怨案例 3(有条件)说:Cannot implicitly convert type 'AnonymousType#1[]' to 'AnonymousType#2[]'。不?:应该能够决定类型,因为我已经提供了匿名 as 的蓝图var data = new[] { new { Text = "Unknown option", Value = -1 } };

解决方案:

@Darin Dimitrov 的回答很好,但我想对匿名类型进行一些测试(简单的情况总是需要它)。正如@Douglas 所怀疑的那样:我assetSequenceRepository提供idaslong而匿名Value则支持intnot long。由于 C# 编译器没有隐式long转换为int,我得到了错误。编译片段是:

public JsonResult ChangeFilterList(int option = 3)
        {
            var data = new[] { new { Text = "Unknown option", Value = long.MaxValue } };
            switch (option)
            {
                case 2: data = _departmentnameRepository.All.Select(x => new { Text = x.DeptName, Value = (long)x.Id }).ToArray();
                    break;
                case 3: data = Session["projectid"] == null
                        ? _assetSequenceRepository.All.Select(x => new { Text = x.AssetShotName, Value = x.Id }).ToArray()
                        : _assetSequenceRepository.FindBy(p => p.ProjectId == (int)Session["projectid"]).Select(x => new { Text = x.AssetShotName, Value = x.Id }).ToArray();
                    break;
                default: data = _userRepository.All.Select(x => new { Text = x.DisplayName, Value = (long)x.UserID }).ToArray();
                    break;
            }            

            return Json(data, JsonRequestBehavior.AllowGet);
        }
4

3 回答 3

5

您在这里对编译器进行了真正的测试。只需编写一个视图模型来结束它的痛苦并使事情更加明确:

public class MyViewModel
{
    public int Value { get; set; }
    public string Text { get; set; }
}

然后将您的 LINQ 查询投影到此视图模型,以避免使用条件运算符和匿名类型可能产生的任何歧义:

public ActionResult ChangeFilterList(int option)
{
    var data = new[] 
    { 
        new MyViewModel { Text = "Unknown option", Value = -1 } 
    };

    switch (option)
    {
        case 2: data = _departmentnameRepository
            .All
            .Select(x => new MyViewModel { Text = x.DeptName, Value = x.Id })
            .ToArray();
            break;
        case 3: data = Session["projectid"] == null
                ? _assetSequenceRepository
                    .All
                    .Select(x => new MyViewModel { Text = x.AssetShotName, Value = x.Id })
                    .ToArray()
                : _assetSequenceRepository
                    .FindBy(p => p.ProjectId == (int)Session["projectid"])
                    .Select(x => new MyViewModel { Text = x.AssetShotName, Value = x.Id })
                    .ToArray();
            break;
        default: data = _userRepository
            .All
            .Select(x => new MyViewModel { Text = x.DisplayName, Value = x.UserID })
            .ToArray();
            break;
    }            

    return Json(data, JsonRequestBehavior.AllowGet);
}
于 2013-10-07T12:08:06.473 回答
4

我的猜测是您的FindBy方法返回的对象的属性类型与您期望的类型不同(例如int?,而不是int)。尝试指定类型转换以确保您的匿名类型具有正确的定义:

case 3: data = Session["projectid"] == null
             ? _assetSequenceRepository.All.Select(x => new { Text = x.AssetShotName, Value = x.Id }).ToArray()
             : _assetSequenceRepository.FindBy(p => p.ProjectId == (int)Session["projectid"]).Select(x => new { Text = (string)x.AssetShotName, Value = (int)x.Id }).ToArray();
        break;

关键变化是:

new { Text = (string)x.AssetShotName, Value = (int)x.Id })
                  ↖    explicit type casts    ↗
于 2013-10-07T12:15:58.463 回答
0

以下测试代码编译得很好:

public void Test(int option, string parameter)
{
    var data = new[] { new { Text = "Unknown option", Value = -1 } };

    switch(option)
    {
        case 2:
            data = Enumerable.Range(1, 4)
                             .Select(x => new { Text = x.ToString(), Value = x })
                             .ToArray();
            break;
        case 3:
            data = (new Random()).Next(2) % 2 == 1
                ? Enumerable.Range(1, 6)
                            .Select(x => new { Text = x.ToString(), Value = x })
                            .ToArray()
                : Enumerable.Range(1, 2)
                            .Select(x => new { Text = x.ToString(), Value = x })
                            .ToArray();
            break;
        default:
            data = Enumerable.Range(1, 3)
                             .Select(x => new { Text = x.ToString(), Value = x })
                             .ToArray();
            break;
    }
}

我只将您的存储库调用更改为Enumerable.Range()Selectlambda 以获得正确的string/int属性值。

我猜想,您所展示的并不完全是您要编译的代码。在您的真实代码中,您有一个名称不匹配的属性(例如,大小写错误)或类型不正确。

您可以通过将鼠标指针悬停在ToArray()通话上来尝试找出答案。将a is new { string Text, int Value }打印在工具提示上。

于 2013-10-07T12:12:15.293 回答