views:

60

answers:

3

I would like to know the approximate XML serialized size of a class instance, without actually serializing the instance. Certainly I can provide a property that explicitly sums together the size of all fields, along with padding for the XML tags that would be generated. However, (1) I'd like to know if there is already a tool that serves this purpose - perhaps an extension method and if not (2) I'd like to know how to make a loop that uses reflection to approximate the size.

Right now I'm making something like this:

    private static readonly int averageTagSize = 20;

    [NonSerialized]
    public int EventSize
    {
        get
        {
            int size = 0;
            FieldInfo[] fields = this.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
            foreach (FieldInfo field in fields)
            {
                size += averageTagSize;
                switch (field.FieldType){
                    case typeof(int):
                        size += 32;
                        break;
                    case typeof(string):
                        string temp = field.GetValue(this) as string;
                        size += temp.Length;
                        break;
                        //...and so on
                }
            }
            return 0;
        }

    }

The above code does not work, as the compiler will not let me switch on type info. Suggestions?

A: 

With XML serialization, there is no straightforward answer since the size all depends on what XML writer options are employed. For example, whether line endings and indentation are used makes a difference as to the final file output.

The approach you're taking could work for a rough estimate. However, you would also have to watch for any attributes defined on classes, properties, and fields that can control how exactly the XML is serialized.

As far as your switch statement goes, the most straightforward replacement would be to use if..else if..else blocks.

Jacob
A: 

While the existing answers are correct about your approach yielding only a very rough estimate, I believe the answer to your immediate question would be to use the string name of the types. I do not have access to a c# compiler at my home, but I believe it would look something like this:

switch (field.FieldType.Name){
                case typeof(int).ToString():
                     .....

I hope that helps!

Real John Connor
A switch can only use contant values in the case statements. Ergo, a "ToString()" call is not valid.
Brent Arias
I will try to get back to you tomorrow from work (where I have VS installed). I know that this is possible in VB, and I would assume with C# as well. At the very least you can "hardcode" the strings into your switch statement.
Real John Connor
A: 

My previous post is erroneous. The answer I gave works in VB, but not in c#. One way to solve this problem would be to hardcode the type names like so:

switch (field.FieldType.Name)
{
    case "Int32":
       size += 32;
       break;
    case "String":
       string temp = field.GetValue(this) as string;
       size += temp.Length;
       break;
}

Alternatively you could use an if statement to avoid the use of hard-coded strings:

foreach (FieldInfo field in fields)
{
    size += averageTagSize;
    if (field.FieldType.Name == typeof(int).Name)
    {
        size += 32;
    }
    else if (field.FieldType.Name == typeof(string).Name)
    {
        string temp = field.GetValue(this) as string;
        size += temp.Length;
    }
}
Real John Connor