views:

346

answers:

1

I've been using resx files for static strings in order to have a central place for changing them. The problem is that I can't change them after the project is built and deployed.

There are some strings that I would like to change after deployment, without restarting the process (so .config files are out).

It's possible to write code that parses a config file (XML/JSON/YAML/?) efficiently, e.g. caches the result for X seconds or monitors it for changes with FileSystemWatcher, but has something like this already been done?

EDIT: using Json.NET and Rashmi Pandit's pointer to CacheDependency I wrote this JSON parsing class that caches the parsed results until the file is changed:

public class CachingJsonParser
{
    public static CachingJsonParser Create()
    {
        return new CachingJsonParser(
            HttpContext.Current.Server,
            HttpContext.Current.Cache);
    }

    private readonly HttpServerUtility _server;
    private readonly Cache _cache;

    public CachingJsonParser(HttpServerUtility server, Cache cache)
    {
        _server = server;
        _cache = cache;
    }

    public T Parse<T>(string relativePath)
    {
        var cacheKey = "cached_json_file:" + relativePath;
        if (_cache[cacheKey] == null)
        {
            var mappedPath = _server.MapPath(relativePath);
            var json = File.ReadAllText(mappedPath);
            var result = JavaScriptConvert.DeserializeObject(json, typeof(T));
            _cache.Insert(cacheKey, result, new CacheDependency(mappedPath));
        }
        return (T)_cache[cacheKey];
    }
}

Usage

JSON file:

{
    "UserName": "foo",
    "Password": "qwerty"
}

Corresponding data class:

class LoginData
{
    public string UserName { get; set; }
    public string Password { get; set; }
}

Parsing and caching:

var parser = CachingJsonParser.Create();
var data = parser.Parse<LoginData>("~/App_Data/login_data.json");
+5  A: 

You can use xml files and store it in the Cache. You can use CacheDependency to reload the cache when any change is made to the file. Links: CacheDependency: CacheItemUpdateCallback :

In your case your Cache should store an XmlDocument as value

Edit: This is my sample code

protected void Page_Load(object sender, EventArgs e)
{
        XmlDocument permissionsDoc = null;

        if (Cache["Permissions"] == null)
        {
            string path = Server.MapPath("~/XML/Permissions.xml");
            permissionsDoc = new XmlDocument();
            permissionsDoc.Load(Server.MapPath("~/XML/Permissions.xml"));
            Cache.Add("Permissions", permissionsDoc,
                            new CacheDependency(Server.MapPath("~/XML/Permissions.xml")),
                           Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
                    CacheItemPriority.Default, new CacheItemRemovedCallback(ReloadPermissionsCallBack));
        }
        else
        {
            permissionsDoc = (XmlDocument)Cache["Permissions"];
        }
}

private void ReloadPermissionsCallBack(string key, object value, CacheItemRemovedReason reason)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(Server.MapPath("~/XML/Permissions.xml"));
        Cache.Insert("Permissions", doc ,
                            new CacheDependency(Server.MapPath("~/XML/Permissions.xml")),
                           Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
                    CacheItemPriority.Default, new CacheItemRemovedCallback(ReloadPermissionsCallBack));
    }
Rashmi Pandit
Awesome, I never heard of CacheDependency before :)
orip
I am using it to cache user permissions which are in an xml file. Everytime there is a change to the xml file, the CacheItemUpdateCallback is called which reloads the xml file into the cache.
Rashmi Pandit
The cool thing (for me) is that it doesn't care what you store, XML or otherwise - very nice!
orip
Thanks ... so my guess is you'll be using it :)
Rashmi Pandit
BTW Rashmi Pandit - I saw you don't need to use the callback or duplicate the parsing logic: just keep the if (Cache[key] == null) check, and add the cache dependency with Cache.Insert(key, value, dependency)
orip