Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auditing and validating changes to C# class and structure properties in a high-performance way

I have several c# structs that give shape to structures in a very large data file. These structs interpret bits in the file's data words, and convert them to first-class properties. Here is an example of one:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TimeF1_MsgDayFmt
{
    // Time Data Words
    public UInt16 TDW1;
    public UInt16 TDW2;
    public UInt16 TDW3;

    /// <summary>
    /// Tens of milliseconds
    /// </summary>
    public UInt16 Tmn
    {
        // Bits.Get is just a helper method in a static class
        get { return Bits.Get(TDW1, 0, 4); }
        set 
        {
            if (value > 9)
                throw new ArgumentOutOfRangeException();

            TDW1 = Bits.Set(TDW1, value, 0, 4); 
        }
    }

    /// Several other properties follow.

I need to do two things, which I think are related. The first is to have the ability to validate the entire class, using a collection of validation rules. I know there are several ways to do this; the one that most appeals to me is to annotate each property with something like this:

[ValidateRange(0,9)]
public UInt16 Tmn
{
    get { return Bits.Get(TDW1, 0, 4); }
    set 
    {
    /// etc.  Will probably no longer throw the ArgumentOutOfRangeException here.

... and then use a Validator class to read all of the property attributes, check each property value against the annotated rule(s), and return a collection of error objects. But I am concerned with how long the Reflection is going to take; these structures have to be extremely high-performing.

public List<Error> Validate(TimeF1_MsgDayFmt original)

The second thing I need to do is to perform auditing on property changes; that is, for each property that has changed from its original value, I need to be able to get a string that says "Property foo changed from bar to baz." To do that, I'd like a way to compare all properties of a "before" and "after" struct, and note the differences.

public List<string> Compare(TimeF1_MsgDayFmt original, TimeF1_MsgDayFmt new)

In both cases, the code will involve iterating over all of the properties and examining each one individually, in a way that is as fast as possible.

How would I approach this?

like image 608
Robert Harvey Avatar asked Oct 10 '11 19:10

Robert Harvey


1 Answers

If the issue is, Does the data read into a struct match additional constraints, you will first of all have to figure out how to write down such constraints. (In your example, you wrote [ValidateRange(0,9)] as one such constraint).

Once you have a means to write down the constraints, then you have to presumably read data into corresponding struct and then check the constraints. (In your example, you suggested the idea of using reflection).

It seems to me the easiest way to write down such constraints, that executes fast, is to simply write them as additional C# code. For each constraint you can imagine, you can add a method of the class that checks the constraint and returns a boolean. You can add a standard constraint "CheckIt" that computes a conjunction of all the individual constraint methods.

It should be easy to write the constraints. I'd expect the C# compiler to inline the other methods, especially if they are small and take no arguments (other than the implied class). That should make them fast.

If the C# compiler won't do it, switch to C++, where you can pretty much force inlining.

like image 86
Ira Baxter Avatar answered Oct 02 '22 18:10

Ira Baxter