More on repositories and delegates

time to read 3 min | 442 words

I like delegates, maybe to the point where I use them too much. I talked about my Repository and that is allowed me to access various sources without caring what the object is, or what is being done with it. Here is a possible implementation of a Finder, which is a read only repository. This code also shows a new pattern that I began to use lately, which is to put delegates in dictionaries, and then invoke them, I find that this is a very powerful way to specialize handling of functionality without much effort.

 

public class Finder
{
    static IDictionary<Type, Func<object, Type, int>> finders;

    static Finder()
    {
        finders = new Dictionary<Type, Func<object, int>>(new IsInstanceOfEqualizer());
        finders.Add(typeof(ActiveRecordBase), delegate(Type type, int id)
        {
            //Get item from the database
            return ActiveRecordBase.FindByPrimaryKey(type, id);
        });

        finders.Add(typeof(Employee), delegate(Type type, int id)
        {
            //Get the user from Active Directory and wrap it in an employee instance
            return new Employee(ActiveDirectoryWrapper.GetUserWithId(id));
        });

        finders.Add(typeof(Enum), delegate(Type type, int id)
        {
            //would be converted to the enum value by Find
            return id;
        });
    }

    public T Find(int id)
    {
        return (T)finders[typeof(T)](typeof(T), id);
    }
}

 

In the case, either the object knows how to save itself (Active Record), or it doesn't need to be saved, so I didn't need to implement a full blown repository (in which case I would've written an interface an each of those would be a class implementing the interface). In my real project, I ended up with the repository-as-a-generic-interface approach, but the one above is a very real possibility for all those that use a real Active Record model (I needed more, so I modified it quite a bit).

Why is this good for? Well, consider other generic code, which can use this Finder object without needing to know what it does (think about security, logging, simple UI, etC).