C# 试图从IEnumerable获取属性时,对象与目标类型不匹配<;TRes>;Func<;T、 TRes>。净4

C# 试图从IEnumerable获取属性时,对象与目标类型不匹配<;TRes>;Func<;T、 TRes>。净4,c#,.net,asp.net-mvc,generics,reflection,C#,.net,Asp.net Mvc,Generics,Reflection,我试图从一个实体中得到一个属性,并对这些值求和。我使用的是泛型,实体的类型和属性的名称在运行时是已知的。以下(简化的)代码编译良好,但在尝试从实体获取属性时抛出“对象不匹配目标类型”。代码如下: public class SomeModel { public int ValueA { get; set; } public int ValueB { get; set; } } public class SomeViewModel

我试图从一个实体中得到一个属性,并对这些值求和。我使用的是泛型,实体的类型和属性的名称在运行时是已知的。以下(简化的)代码编译良好,但在尝试从实体获取属性时抛出“对象不匹配目标类型”。代码如下:

    public class SomeModel
    {
        public int ValueA { get; set; }
        public int ValueB { get; set; }
    }

    public class SomeViewModel
    {
        public int ViewValue { get; set; }
    }

    public class HomeController : Controller
    {

        public ActionResult Index()
        {
            IEnumerable<SomeModel> data = GetData();

            var result = SumValues(data, a => new SomeViewModel { ViewValue = a.ValueA });

            return Content(string.Format("Total is: {0}", result));
        }

        private int SumValues<T, TRes>(IEnumerable<T> data, Func<T, TRes> transformation)
        {
            var transformedData = data.Select(transformation);
            Type type = typeof(TRes);
            PropertyInfo property = type.GetProperty("ViewValue");
            IEnumerable<int> listOfValues = property.GetValue(transformedData, null) as IEnumerable<int>;
            var sum = listOfValues.Sum();

            return sum;
        }

        private IEnumerable<SomeModel> GetData()
        {
            var data = new List<SomeModel>();
            Random random;
            for (int i = 0; i < 1000; i++)
            {
                random = new Random(i);
                data.Add(new SomeModel { ValueA = random.Next(5,100), ValueB = random.Next(20,80) });
            }
            return data;
        }
    }
公共类模型
{
公共int值a{get;set;}
公共int值b{get;set;}
}
公共类视图模型
{
公共int视图值{get;set;}
}
公共类HomeController:控制器
{
公共行动结果索引()
{
IEnumerable data=GetData();
var result=SumValues(数据,a=>newsomeviewmodel{ViewValue=a.ValueA});
返回内容(string.Format(“总计为:{0}”,结果));
}
私有int-SumValues(IEnumerable数据,Func转换)
{
var transformedData=数据。选择(转换);
类型=类型(TRes);
PropertyInfo属性=type.GetProperty(“ViewValue”);
IEnumerable listOfValues=property.GetValue(transformedData,null)作为IEnumerable;
var sum=listOfValues.sum();
回报金额;
}
私有IEnumerable GetData()
{
var data=新列表();
随机;
对于(int i=0;i<1000;i++)
{
随机=新随机(i);
Add(newsomemodel{ValueA=random.Next(5100),ValueB=random.Next(20,80)});
}
返回数据;
}
}
我在这里生成假数据,但真正的应用程序使用EF从数据库中获取数据。泛型对我来说是新的,因此,如果您能给我提供正确方向的建议,我将不胜感激。

在这一行:

IEnumerable<int> listOfValues = 
                       property.GetValue(transformedData, null) as IEnumerable<int>;
但一个更干净的解决方案是完全避免反射,因为这里不需要反射:

interface IViewValue
{
    int ViewValue { get; set; }
}

public class SomeViewModel : IViewValue
{
    public int ViewValue { get; set; }
}

private int SumValues<T, TRes>(IEnumerable<T> data, Func<T, TRes> transformation)
                                            where TRes : IViewValue
{
    var transformedData = data.Select(transformation);
    IEnumerable<int> listOfValues = transformedData.Select(i => i.ViewValue);
    var sum = listOfValues.Sum();

    return sum;
}
接口IViewValue
{
int ViewValue{get;set;}
}
公共类SomeViewModel:IViewValue
{
公共int视图值{get;set;}
}
私有int-SumValues(IEnumerable数据,Func转换)
其中TRes:IViewValue
{
var transformedData=数据。选择(转换);
IEnumerable listOfValues=transformedData.Select(i=>i.ViewValue);
var sum=listOfValues.sum();
回报金额;
}

太棒了!谢谢你这么快回答。两种选择都很有效。最后我使用了第一个,因为属性名可以是任何东西,只要用一个标志来装饰,表明它需要一个总数。再次感谢你。
interface IViewValue
{
    int ViewValue { get; set; }
}

public class SomeViewModel : IViewValue
{
    public int ViewValue { get; set; }
}

private int SumValues<T, TRes>(IEnumerable<T> data, Func<T, TRes> transformation)
                                            where TRes : IViewValue
{
    var transformedData = data.Select(transformation);
    IEnumerable<int> listOfValues = transformedData.Select(i => i.ViewValue);
    var sum = listOfValues.Sum();

    return sum;
}