Deep inside the SR type: curiosities, improvements and some generics code too

Note: this entry has moved.

Here I’m assuming you’re already familiar with the SR type; if you’re not, then reading this post will definitively help.

 

In this post I’m going to detail a few curiosities I found while dissecting the SR type plus some suggested improvements.

 

Getting the assembly where a type is implemented

 

I can hear you saying: “…This is really an easy one, just do”:

 

YourType.GetType ().Assembly

 

Sounds obvious; but now, if you peek at SR’s internal constructor you’ll find that they get to the assembly by using:

 

YourType.GetType ().Module.Assembly

 

So I asked myself: “Why in the world are they getting to the assembly by using the Module property?”

 

First thing I thought was the ResourceManager not being clever enough to resolve resources located in different modules of a multi-module assembly, although that is not the case in the .NET fx -where all assemblies are composed of a single module- I thought they may have coded it that way just for “forward-compatibility”.

 

I fired up a console and using csc.exe and al.exe hacked up a simple two-module assembly having types and resources in each one of the modules. Then I used TypeOne.GetType().Assembly, where TypeOne is defined in module A and tried to access resources stored in module B; I expected this to miserably fail so I could confirm my simple theory. The results shown that ResourceManager is actually clever enough to find any resources no matter where they’re stored; it will consult the assembly’s manifest where resources entries contains info about the module file where they reside and from there it will properly get to the resource.

 

Code bloating

 

You know SR includes about 22 utility methods (counting overloads) to provide a strongly-typed way of handling resources. Basically what every GetXXX method does is to use the resource manager to get an object reference and then cast that reference to the specific type they’re handling with, something like this:

 

static public double GetDouble (CultureInfo ci, string resid) {

     double num = 0;

     SR sr = SR.GetLoader ();
     if (sr != null)

          object o = sr.resources.GetObject (resid, ci);

     if (o != null)

          num = (double) o;

     return num;

}

 

Note the above lines in bold, they’re repeated in every GetXXX method (GetInt, GetFloat, GetChar, etc.)

There is a GetObject method that does exactly the same and could have been used by any of these methods, so why is this code repeated all along? The only reason I can think of is C# compiler’s inlining feature.

 

 

A generics-enabled SR

 

With the support for generics in Whidbey it will be possible to reduce the code-bloating nature of SR to this minimum expression:

 

 

static public T Get<T> (CultureInfo ci, string resid) {

     T res = T.default;

     object o = SR.GetLoader ()._resMgr.GetObject (resid, ci);

           

     if (o != null)

                res = (T)o;

           return res;

     }

 

static public T Get<T> (string resid) {

     return SR.Get<T> (null, resid);

}

 

Don’t you think generics just rocks?

 

Download a skeleton SR type using generics from here (you’ll need whidbey to compile).

4 Comments

  • Well, isn't Generics a great way to reduce boxing and unboxing? There's still a lot of unboxing going on with the SR, so if the resource manager is rewritten with generics support, i'm sure you could get an even simpler



    return SR.GetLoader()._resMgr.Get&lt;T&gt;(resid, ci) as T;

    ?

  • Well, the &quot;as T&quot; could fail if the &lt;T&gt; parameter happens to be a ValueType. Therefore, it would actually have to be a direct cast:



    return (T) SR.GetLoader()._resMgr.Get&lt;T&gt;(resid, ci);

  • Well... how sure are you? :-)



    I'm pretty sure you won't be able to use 'T' with the 'as' operator without applying some class constrains first.

  • Sebastien,



    Re-reading your comment I'm now seeing that you're talking about rewriting ResourceManager as well as the SR type, thats good but I still believe the compiler will complain about using 'as' there without some constrains in place.



    Cazzu,



    I think you're not considering the case of GetObject returning null and &lt;T&gt; being a value type. Thats why I used the T.default at the method's very beginning. BTW, when are you gonna post some pics about Agus?



    Thank you both for your comments,

    Vic.



Comments have been disabled for this content.