VB.Net将linq-expression作为参数传递,并使用该表达式设置对象属性

时间:2014-01-23 13:00:27

标签: .net vb.net linq

我想创建一个函数,它接受一个对象列表,循环遍历它们并将customername附加到每个对象。目标是调用此方法的用户将告诉对象中的哪个属性包含customernumber,以及用于设置从db获取的customername的属性。

现在我已经完成了很多逻辑,但是我正在努力使它尽可能强大地输入。所以我想我可以使用Linq表达式作为参数。这就是我现在所拥有的:

Public Shared Sub FillCustomerNames(Of TModel As Class)(objects As IEnumerable(Of TModel),
                                                      customerNumberExpression As Func(Of TModel, Integer),
                                                      customerNameExpression As Func(Of TModel, String))

    Dim customerNumbers As List(Of Integer) = objects.Select(customerNumberExpression).Distinct().ToList()

    ' Fetch names from the database...
    Dim customerNames = From c In Customers...

    ' Combine original objects with names
    Dim joinResult = From original In objects
                     Let customerNumber As Integer = customerNumberExpression.Invoke(original)
                    Join customer In customerNames On customerNumber Equals customer.CustomerNumber
                    Select original, customer.CustomerName

    For Each item In joinResult
        ' How to set the property in the expression?
        ' item.original.(property wanted) = item.customerName
    Next
End Sub

我希望能够用这样的东西来称呼它:

    FillCustomerNames(Of ADDRESS)(addresses,
                                    Function(a) a.CustomerNumber,
                                    Function(a) a.CustomerName)

现在Customernumber表达式(我用来从对象获取customernumber)工作正常。但你怎么做那个二传手呢?我想我不能用这种表达方式做到这一点?我需要一个动作吗?什么是最简单的方法。

我知道我可以使用反射并将属性名称作为字符串传递,但它不是强类型的,因为它会是。

任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:1)

  

但你怎么做那个二传手呢?我想我不能用这种表达方式做到这一点?我需要一个动作吗?

是。我正在从C#(在我的脑海中)翻译成你的VB.NET,所以如果我的语法错误就道歉。

您已经知道如何将 getter 传递给您的方法 - 作为Func(Of T, Integer),需要T返回 Integer。您现在想要的是将 setter 传递给您的方法。一个setter(在这种情况下)是一个需要TString并且......做某事,然后返回 nothing 的东西。为此,您可以使用Action(Of T, String),如下所示:

您的方法签名变为

Public Shared Sub FillCustomerNames(Of TModel As Class)(
    objects As IEnumerable(Of TModel),
    customerNumberGetter As Func(Of TModel, Integer),
    customerNameSetter As Action(Of TModel, String))

(注意我已从参数名称中删除Expression,因为这可能与Linq Expression功能混淆,后者未在此处使用)

而且:

For Each item In joinResult
    ' How to set the property in the expression?
    ' item.original.(property wanted) = item.customerName
Next

变得简单

For Each item In joinResult
    customerNameSetter(item.original, item.customerName)
Next

请记住,customerNameSetter是一个Action,因此可以简单地调用,就像它是一个“真正的”方法一样。

通话网站将成为:

FillCustomerNames(Of ADDRESS)(addresses,
                                Function(a) a.CustomerNumber,
                                Sub(a, name) a.CustomerName = name)

(这是我不完全确定用于声明lambda Sub的VB.NET语法的地方)