使用expressions / lambda设置属性值的通用方法

时间:2012-02-14 01:29:33

标签: c# .net linq generic-list

我试图找到一种通用的方法来为lambda表达式指定的属性赋值,查看下面的示例代码,ConverToEntities方法的签名如何看?它将如何被调用?

static void Main()
{
    List<long> ids = new List<long> {1, 2, 3};

    //Non generic way
    List<Data> dataItems = ids.ConvertToDataItems();

    //Generic attempt!!
    List<Data> differntDataItems =
        ids.ConvertToEntities<Data>( p => p.DataId );
}

public class Data
{
    public long DataId;
    public string Name;
}

public static class ExtensionMethods
{
    public static List<Data> ConvertToDataItems(this List<long> dataIds)
    {
        return dataIds.Select(p => new Data { DataId = p }).ToList();
    }

    public static List<T> ConvertToEntities<TProp>(
        this List<long> entities, Func<TProp> lambdaProperty )
    {
        return entities.Select(p => new T {lambdaProperty} ).ToList();
    }
}

3 个答案:

答案 0 :(得分:4)

确定。我能得到的最接近的是:

 class Program
    {
        static void Main(string[] args)
        {
            List<long> ids = new List<long> { 1, 2, 3 };

            //Non generic way
            List<Data> dataItems = ids.ConvertToDataItems();

            //Generic attempt!!

            Func<long, Data> selector = (p => new Data { DataId = p });
            List<Data> differntDataItems = ids.ConvertToEntities<Data>(selector);
        }
    }

    public class Data
    {
        public long DataId;
        public string Name;
    }

    public static class ExtensionMethods
    {
        public static List<Data> ConvertToDataItems(this List<long> dataIds)
        {
            return dataIds.Select(p => new Data { DataId = p }).ToList();
        }

        public static List<TProp> ConvertToEntities<TProp>(this List<long> entities, Func<long, TProp> selector)
        {
            return entities.Select(selector).ToList();
        }
    }

这很有效。

我觉得你对自己真正想要的回归类型感到困惑。能够在方法调用或smth中指定我们想要的内容会很酷。例如:

    public static List<TProp> ConvertToEntities<T, TProp>(List<T> entities, Func<T, TProp> selector)
    {
        return entities.Select(selector).ToList();
    }

这为我们提供了更多返回类型的灵活性。但由于我们使用扩展来做这件事,我认为这是不切实际的,因为我们需要知道我们正在扩展的类型:

this List<long> entities,

好问题。

编辑代码建议修复。

答案 1 :(得分:2)

你可以做这样的事情,但它不是那么简单或好看。 lambda p => p.DataId为您提供了属性的get访问器。您可以使用Expression来获取setter,但最好直接在lambda中使用setter:

List<Data> differntDataItems =
    ids.ConvertToEntities<long, Data>((p, i) => p.DataId = i);

实现如下:

public static List<T> ConvertToEntities<TProp, T>(
    this List<TProp> dataIds, Action<T, TProp> lambdaProperty)
    where T : new()
{
    return dataIds.Select(
        p =>
        {
            var result = new T();
            lambdaProperty(result, p);
            return result;
        }).ToList();
}

答案 2 :(得分:1)

我相信@Zortkun对于返回类型是正确的。请尝试以下方法:

public static List<TProp> ConvertToEntities<TProp>(
    this List<long> entities, Func<long, TProp> lambdaProperty )
{
    return entities.Select(lambdaProperty).ToList();
}

你可以这样称呼它:

ids.ConvertToEntities<Data>( p => new Data { DataId = p } );