• ASP.NET RSS Toolkit

    dmitryr's blog : ASP.NET RSS Toolkit

  • My first generic method

    Since starting to use .NET 2.0, I've made quite a lot of use of the Generic Collection classes.

    Today however was the first time I've created my own generic method that adapts to the required type for each instance.

    The use of the method is to replace the following kind of code:

        Dim rowTest As dsTests.TESTSRow
    
        rowTest = dtTests(0)
    
        If rowTest.TEST\_PUBLISHED <> test.Published Then
    
            OnDataItemChanged(dtTests.TEST\_PUBLISHEDColumn.ColumnName, rowTest.TEST\_PUBLISHED, test.Published)
    
            rowTest.TEST\_PUBLISHED = test.Published
    
        End If
    

    Basically, I'm checking if the value has changed, and if it has then I update the DataRow property, and eventually I call a DataAdapter to send the updates back to the database. By doing the compare, I'm only sending real changes back to the database.

    My first step was to create a helper method that took an object as a parameter like this:

    Public Shared Sub UpdateDataRowItem1(ByVal row As Data.DataRow, ByVal column As Data.DataColumn, ByVal newValue As Object)
    
        Dim oldValue As Object = row(column.ColumnName)
    
        If oldValue <> newValue Then
    
            row(column.ColumnName) = newValue
    
            OnDataItemChanged(column.ColumnName, oldValue, newValue)
    
        End If
    
    End Sub
    

    But as the squiggly lines appeared in Visual Studio, I realised that this wasn't going to work if I stuck with the general Object data type - you can't use <> with Object types! The alternatives were to create separate versions of the method for the different types, or I realised I could make use of generics to do the same thing but in a much easier to maintain way.

    My first question was "Can you actually have generic methods?", as I didn't really want a whole class to do this. Thanksfully, the answer is Yes. So I updated the method to look like this:

    Public Shared Sub UpdateDataRowItem2(Of t)(ByVal row As Data.DataRow, ByVal column As Data.DataColumn, ByVal newValue As t)
    
        Dim oldValue As t = CType(row(column.ColumnName), t)
    
        If oldValue <> newValue Then
    
            row(column.ColumnName) = newValue
    
            OnDataItemChanged(column.ColumnName, oldValue, newValue)
    
        End If
    
    End Sub
    

    Getting closer, but it was still complaining - "Operator '<>' is not defined for types 't' and 't'". Going back to check the documention, I noticed one of the examples used a 'constraining type' on the type parameter. That is just what I needed too, so the final version is as follows:

    Public Shared Sub UpdateDataRowItem(Of t As IComparable)(ByVal row As Data.DataRow, ByVal column As Data.DataColumn, ByVal newValue As t)
    
        Dim oldValue As t = CType(row(column.ColumnName), t)
    
        If oldValue.CompareTo(newValue) <> 0 Then
    
            row(column.ColumnName) = newValue
    
            OnDataItemChanged(column.ColumnName, oldValue, newValue)
    
        End If
    
    End Sub
    

  • Unit Testing Events with Anonymous Delegates in .NET 2.0

    How do you unit test your event code? You use Anonymous Delegates

    Here's a sample unit test that I've created that makes use of this technique:

        \[TestMethod()\]
    
        public void UpdateTestTimesTest()
    
        {
    
            object expected = UniSA.UniSAnet.SmartMark.DataAccess.DataItemChangedEventArgs.ChangeType.Update;
    
            object actual = null;
    
            UniSA.UniSAnet.SmartMark.DataAccess.TestComponent.DataItemChanged += delegate(object sender, UniSA.UniSAnet.SmartMark.DataAccess.DataItemChangedEventArgs e)
    
            {
    
                actual = e.Change;
    
            };
    
            Test test = UniSA.UniSAnet.SmartMark.DataAccess.TestComponent.GetTest(UnitTestingTestId);
    
            test.MinutesAllowed += 1;
    
            UniSA.UniSAnet.SmartMark.DataAccess.TestComponent.UpdateTestTimes(test);
    
            Assert.AreEqual(expected, actual);
    
        }