Monday, July 24, 2006

Recycling messages (or how not to be responsible for translating error messages).

In the continuing saga of my replacement for ObjectDataSource and ObjectDataSourceView, I have had to reimplement some of the methods in those classes. This is done, of course, by using Reflector to see what is currently there and tweaking appropriately. In the process of replacing a method, you probably want to check the same argument conditions and throw the same exceptions as the originals in System.Web.dll. If you can find a way to expose the existing messages and reuse them, you get the added benefit of not having to worry about translation/localization of those error messages. To that end, here's my ExposedSR class that hoists the messages I need from System.Web.dll

internal static class ExposedSR
{
    private static readonly ResourceManager s_Resources = new ResourceManager("System.Web", typeof(ObjectDataSourceView).Assembly);
 
    internal static string GetString(string name)
    {
        return s_Resources.GetString(name, null);
    }
 
    internal static string GetString(string name, params object[] args)
    {
        string text = s_Resources.GetString(name, null);
 
        if (args == null || args.Length == 0)
        {
            return text;
        }
 
        // clip all the string arguments to less than 1K length
        for (int index = 0; index < args.Length; index++)
        {
            string argString = args[index] as string;
 
            if (argString != null && argString.Length > 0x400)
            {
                args[index] = argString.Substring(0, 0x3fd) + "...";
            }
        }
 
        return string.Format(CultureInfo.CurrentCulture, text, args);
    }
 
    internal static readonly string Pessimistic = "ObjectDataSourceView_Pessimistic";
    internal static readonly string InsertNotSupported = "ObjectDataSourceView_InsertNotSupported";
    internal static readonly string UpdateNotSupported = "ObjectDataSourceView_UpdateNotSupported";
    internal static readonly string DeleteNotSupported = "ObjectDataSourceView_DeleteNotSupported";
    internal static readonly string InsertRequiresValues = "ObjectDataSourceView_InsertRequiresValues";
    internal static readonly string Update = "DataSourceView_update";
    internal static readonly string Delete = "DataSourceView_delete";
    internal static readonly string InvalidViewName = "DataSource_InvalidViewName";
    internal static readonly string DataObjectPropertyNotFound = "ObjectDataSourceView_DataObjectPropertyNotFound";
    internal static readonly string DataObjectPropertyReadOnly = "ObjectDataSourceView_DataObjectPropertyReadOnly";
}

The trick here is to create a class that mirrors the normal SR class that is automatically generated by the resources compiler, but coopt it to use the assembly containing the resources you really want. Then readonly strings are there to ease readability when using ExposedSR.

No comments: