locked
Sum object properties by its attribute using LINQ from multiple list RRS feed

  • Question

  • Hallo I would like to write a LINQ query to sum object properties based on their attribute .

    I have Datagridview like below. I want to loop through Datagridview Category column and write a sum of weights from two bindinglists. 

    Public Class Category1    
        
        <Category("WeightVegitables")> _
        Public Property Tomatto() As Integer
    
        <Category("WeightFruits")> _ 
        Public Property Apple() As Integer
    
        <Category("WeightFruits")> _ 
        Public Property Banana() As Integer
       
        <Category("WeightMeats")> __
        Public Property Pork() As Integer
    
        <Category("WeightMeats")> __
        Public Property Fish() As Integer
           
    End Class
    Public Class Categories1
    	Inherits System.ComponentModel.BindingList(Of Category1)
    End Class
    
    
    
    
    Public Class Category2    
        
        <Category("WeightVegitables")> _
        Public Property Brinjal() As Integer
    
        <Category("WeightFruits")> _ 
        Public Property Orange() As Integer
       
        <Category("WeightMeats")> __
        Public Property Chicken() As Integer
           
    End Class
    Public Class Categories2
    	Inherits System.ComponentModel.BindingList(Of Category2)
    End Class

    Or is there any alternative method to the example but without attributes? 

    Can i have more than 1 attribute to a property?

    Thanks





    • Edited by Shan1986 Tuesday, November 24, 2020 8:22 PM
    Tuesday, November 24, 2020 12:51 PM

Answers

  • Hi Shan1986,

    Thank you for posting here.

    I make a test based on your description, and here's my custom attribute 'Category'.

    <System.AttributeUsage(System.AttributeTargets.Property)>
    Public Class Category
        Inherits System.Attribute
    
        Public weightCategory As String
        Sub New(ByVal category As String)
            weightCategory = category
        End Sub
    End Class

    The following example calculates the sum of ‘WeightVegitables’, ‘WeightFruits’ and ‘WeightMeats’ from a given ‘Categories1’.

        Private WeightVegitablesCount As Integer
        Private WeightFruitsCount As Integer
        Private WeightMeatsCount As Integer
        Private lst As Categories1 = New Categories1()
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            lst.Add(New Category1() With {
                .Tomatto = 10,
                .Apple = 20,
                .Banana = 30,
                .Fish = 40,
                .Pork = 50
            })
            lst.Add(New Category1() With {
                .Tomatto = 11,
                .Apple = 22,
                .Banana = 33,
                .Fish = 44,
                .Pork = 55
            })
            lst.Add(New Category1() With {
                .Tomatto = 12,
                .Apple = 23,
                .Banana = 32,
                .Fish = 46,
                .Pork = 57
            })
        End Sub
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            For Each prop In GetType(Category1).GetProperties()
                Dim ca = CType(prop.GetCustomAttributes(GetType(Category), False).FirstOrDefault(), Category)
                Dim value As Integer = lst.Sum(Function(x) CInt((x.GetType().GetProperty(prop.Name).GetValue(x))))
    
                Select Case ca.weightCategory
                    Case "WeightVegitables"
                        WeightVegitablesCount += value
                    Case "WeightFruits"
                        WeightFruitsCount += value
                    Case "WeightMeats"
                        WeightMeatsCount += value
                End Select
            Next
            MessageBox.Show($"WeightVegitables: {WeightVegitablesCount} WeightFruits:{WeightFruitsCount} WeightMeats:{WeightMeatsCount}")
        End Sub

    The above code also applies to 'Categories2'.

    Hope it could be helpful.

    Best Regards,

    Xingyu Zhao


    Visual Basic and CLR forum will be migrating to a new home on Microsoft Q&A! (VB.NET and CLR) We invite you to post new questions in the new home on Microsoft Q&A ! For more information, please refer to the sticky post(VB.NET and CLR).


    Wednesday, November 25, 2020 6:52 AM

All replies

  • Hi Shan1986,

    Thank you for posting here.

    I make a test based on your description, and here's my custom attribute 'Category'.

    <System.AttributeUsage(System.AttributeTargets.Property)>
    Public Class Category
        Inherits System.Attribute
    
        Public weightCategory As String
        Sub New(ByVal category As String)
            weightCategory = category
        End Sub
    End Class

    The following example calculates the sum of ‘WeightVegitables’, ‘WeightFruits’ and ‘WeightMeats’ from a given ‘Categories1’.

        Private WeightVegitablesCount As Integer
        Private WeightFruitsCount As Integer
        Private WeightMeatsCount As Integer
        Private lst As Categories1 = New Categories1()
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            lst.Add(New Category1() With {
                .Tomatto = 10,
                .Apple = 20,
                .Banana = 30,
                .Fish = 40,
                .Pork = 50
            })
            lst.Add(New Category1() With {
                .Tomatto = 11,
                .Apple = 22,
                .Banana = 33,
                .Fish = 44,
                .Pork = 55
            })
            lst.Add(New Category1() With {
                .Tomatto = 12,
                .Apple = 23,
                .Banana = 32,
                .Fish = 46,
                .Pork = 57
            })
        End Sub
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            For Each prop In GetType(Category1).GetProperties()
                Dim ca = CType(prop.GetCustomAttributes(GetType(Category), False).FirstOrDefault(), Category)
                Dim value As Integer = lst.Sum(Function(x) CInt((x.GetType().GetProperty(prop.Name).GetValue(x))))
    
                Select Case ca.weightCategory
                    Case "WeightVegitables"
                        WeightVegitablesCount += value
                    Case "WeightFruits"
                        WeightFruitsCount += value
                    Case "WeightMeats"
                        WeightMeatsCount += value
                End Select
            Next
            MessageBox.Show($"WeightVegitables: {WeightVegitablesCount} WeightFruits:{WeightFruitsCount} WeightMeats:{WeightMeatsCount}")
        End Sub

    The above code also applies to 'Categories2'.

    Hope it could be helpful.

    Best Regards,

    Xingyu Zhao


    Visual Basic and CLR forum will be migrating to a new home on Microsoft Q&A! (VB.NET and CLR) We invite you to post new questions in the new home on Microsoft Q&A ! For more information, please refer to the sticky post(VB.NET and CLR).


    Wednesday, November 25, 2020 6:52 AM
  • Hallo Xingyu. Thanks for the answer. I get error when i run it one this line ca was nothing and 

     "Select Case ca.weightCategory " 

    System.NullReferenceException: 'Object reference not set to an instance of an object.'

    Thanks.

    Wednesday, November 25, 2020 9:31 AM
  • Hi,

    Did you use the custom 'Category' I provided to make the test?

    I can get the correct test result.

    Best Regards,

    Xingyu Zhao


    Visual Basic and CLR forum will be migrating to a new home on Microsoft Q&A! (VB.NET and CLR) We invite you to post new questions in the new home on Microsoft Q&A ! For more information, please refer to the sticky post(VB.NET and CLR).

    Thursday, November 26, 2020 1:37 AM
  • Thanks Xingyu. It worked my mistake.
    Thursday, November 26, 2020 7:22 AM