views:

66

answers:

1

Thanks @dtb for help, he advised really need piece of code for generic service locator

static class Locator
{
    private static class LocatorEntry<T> where T : ...
    {
        public static IDataManager<T> instance;
    }

    public static void Register<T>(IDataManager<T> instance) where T : ...
    {
        LocatorEntry<T>.instance = instance;
    }

    public static IDataManager<T> GetInstance<T>() where T : ...
    {
        return LocatorEntry<T>.instance;
    }
}

However in my previous version I used reflection on assembly to discover a hundred of DataManager's

I want to write an method discover like the following

void Discover()
        {
            var pManager = new ProtocolSQLDataManager();
            Register(pManager);

            var rManager = new ResultSQLDataManager();
            Register(rManager);

            var gType = typeof(ISQLDataAccessManager<>);

            foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
            {               
                if (type.IsSubclassOf(gType) && !type.IsAbstract))
                {
                    var manager = Activator.CreateInstance(type);
                    // put something here in order to make next line of code works
                    Register<T>(manager);
                }
            }
        }

How to cast type to appropriate type in order to make Register working( and call appropriate Register ?

UPDATE: I figured it out

            foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
            {
                if ( type.GetInterface("IDataAccessManager`1") != null && !type.IsAbstract)
                {
                    var manager = Activator.CreateInstance(type);
                    var t = type.GetInterface("IDataAccessManager`1").GetGenericArguments()[0];
                    typeof(GenLocator)
                        .GetMethod("Register")
                        .MakeGenericMethod(t)
                        .Invoke(null, new[] { manager });
                }
            }
+3  A: 

You need to call Register using reflection, like this:

typeof(Locator)
    .GetMethod("Register")
    .MakeGenericMethod(type)
    .Invoke(null, manager);
SLaks
how, can you show a snippet ?
vittore
@SLaks: thanks , but i need to provide type `T` for `MakeGenericMethod` and how i can get it form my type which is child of `BaseDataManager<T>` ?
vittore
That's done by `MakeGenericMethod`. http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.makegenericmethod.aspx
SLaks
IMO two small casts are **way** less ugly than using reflection to register the types... http://stackoverflow.com/questions/2656067
dtb
@dtb: but in case i discover types with reflection, I do this crazy stuff only once, say in static constructor, otherwise I would use casting each time when i will ask locator for instance. From other hand it still much better my older approach when i have non generic interfaces and used to use castings everywhere because methods was non generic...
vittore
@dtb: Also for your second snippet I need the same reflection to register instances, don't I ?
vittore