Sunday, May 1, 2011

Use ResourceReader to create a HybridDictionary of resources.

I'm using a ResourceReader to read an embedded resx resource and I want to store it at a class level in a member variable. I'm want to store it as a HybridDictionary but don't see an easy way of doing it.

Class member

private IEnumerable<DictionaryEntry> dictionary;

Class initalize

Assembly asm = Assembly.GetExecutingAssembly();
Stream resourceStream = asm.GetManifestResourceStream("MagicBeans");

using (ResourceReader r = new ResourceReader(resourceStream))
{
    IEnumerable<DictionaryEntry> dictionary = r.OfType<DictionaryEntry>();
}

Properties

public string Something { get { return dictionary["Something"].Value;  }} 
public string ThatThing { get { return dictionary["ThatThing"].Value;  }}

However, the IEnumerable<DictionaryEntry> isn't working the way I like and Im currently looking at doing something LINQ'y like; .First(x => x.Key=="Something").Value

From stackoverflow
  • IEnumerable does not support access by key (the dictionary["something"] part in your code), to access data that way you'd need your dictionary property to be an IDictionary class. Something like:

    private IDictionary<string, object> dictionary;
    

    Then you would need to parse the data that you draw back from the assembly to populate the dictionary:

    Assembly asm = Assembly.GetExecutingAssembly();
    Stream resourceStream = asm.GetManifestResourceStream("MagicBeans");
    
    dictionary = new Dictionary<string, object>();
    
    using (ResourceReader r = new ResourceReader(resourceStream))
    {
        foreach(DictionaryEntry entry in r.OfType<DictionaryEntry>())
        {
           dictionary.Add(entry.Key.ToString(), entry.Value);
        }
    }
    

    Finally the properties wouldn't need the Value call:

    public string Something { get { return dictionary["Something"];  }} 
    public string ThatThing { get { return dictionary["ThatThing"];  }}
    

    These properties will throw an exception if the key doesn't exist in the dictionary, so you may want to check for that first.

    Your LINQ solution should also work, but at the cost of enumerating though the list to find the correct entry each time the property is requested.

    Dead account : +1. Brilliant first answer!
  • To convert the resource into a dictionary, you can use the following:

    using (var reader = new ResourceReader(resource))
    {
      var dictionary = reader
        .Cast<DictionaryEntry>()
        .Aggregate(new Dictionary<string, object>(), (d, e) => { d.Add(e.Key.ToString(), e.Value); return d; });
    
      Console.WriteLine(dictionary["Foo"]);
    }
    

0 comments:

Post a Comment