views:

172

answers:

2

I am working on a client (Silverlight) interface to a collection of webmethod. And I am trying to avoid writing any custom code for every webmethod. So I have created a ServiceCall<TResult> to handle each call, TResult specifies the return type of the service (I use XmlSerializer to create the returned instance). The client class exposes a function matching each webmethod, and all that function has to do is to create a new instance of ServiceCall<TResult>, with the TResult specified as the expected return type of the method. And that works just fine.

I am also using Ninject (dependency injector) to try and keep everything independent. Ninject supports open generics, whichs works out great with my ServiceCall<TResult>.

But it also means that I'm injecting a reference to the Ninject container. Which hides the dependency on ServiceCall<TResult> being bound to the container. So I would like to instead inject a factory for creating my ServiceCall<TResult> instances. Which is not tricky, but I would like to make it a generic generic factory. Meaning I would like to have something like Factory<T<>> which would have a method public T<TU> Createinstance<TU>().

But I have no idea how I could create generic class with a type parameter that is itself an open genric.

Is it event posible in .Net? - Or do I have to create a specific ServiceCallFactory?

Edit: I am using interfaces for the dependencies, but there's no need to mix them into the question here, so I edited that out of the question.

In responce to Timwi: The common way to use dependency injection (DI) is to bind an interface to your implementation, only the container knows of these bindings. You then code up against the interfaces instead. This brings a ton of advantages. More than I can mention here.
Anyway it also rules out the static classes (since that would be a dependency on a specific class). Instead I'll instruct the container (Ninject in this case) to always hand me the same instance for the factory interface, in a singleton like behavior.
This rules out the public static class Factory<T> option, because it is static, and if it is not static I would need to now every type of T I'm gonna use, somewhat defeating the purpose of having a generic class.
The suggestion of having a non-generic class with a "totally generic" method (as in I pass in ServiceCall<MyResult> instead of just MyResult), is what more or less what I am doing now (minus the static class part). The Ninject container has an Get method that work like your second suggestion.
The problem with this is two part; firstly it makes my code directly dependent on one container (Ninject), but this is not really that big a problem to me. What does annoy me is that if you look at me Client from the outside, you'll only see a dependency on Ninject. You wont know until you run try to make a call that client needs an implementation of ServiceCall registered with Ninject to work.
But if the Client contructor took a parameter of type Factory>, then it would much clearer.

In any case I would think this would be a common issue, so either there a common solution, or it is not a common issue and I am trying to do something stupid ;) I am still not that into dependency injection, so that may very well be the case.

+1  A: 

So if I understand you right, you’d have a class looking a bit like this:

public static class Factory<T<>>
{
    public static T<TU> CreateInstance<TU>() { /* ... */ }
}

and then you’d call it how? Like this?

var myServiceCall = Factory<ServiceCall<>>.CreateInstance<MyResult>();

What stops you from simply declaring the factory like this...

public static class Factory<T>
{
    public static T CreateInstance() { /* ... */ }
}

... or this ...

public static class Factory
{
    public static T CreateInstance<T>() { /* ... */ }
}

... and then generating your instance like this?

var myServiceCall = Factory<ServiceCall<MyResult>>.CreateInstance();
var myServiceCall = Factory.CreateInstance<ServiceCall<MyResult>>();

I’m sorry if I’m being dumb, but I’d probably need to know how Ninject works and how it allows you to pass in a factory.

Timwi
I'll leave a comment in the question since space is a bit short here.
Lillemanden
A: 

Is this what you are looking for: Generic Factory Pattern

namespace GenericFactoryPatternTestApp
{
    public class Factory< T >
    {
        private readonly Dictionary< string, Type > _factoryDictionary = new Dictionary< string, Type >();

        public Factory()
        {    
            Type[] types = Assembly.GetAssembly(typeof (T)).GetTypes();

            foreach (Type type in types)
            {
                if (!typeof (T).IsAssignableFrom(type) || type == typeof (T))
                {
                    // Incorrect type
                    continue;
                }

                // Add the type
                _factoryDictionary.Add(type.Name, type);
            }
        }

        public T Create< V >(params object[] args)
        {
            return (T) Activator.CreateInstance(_factoryDictionary[typeof (V).Name], args);
        }
    }
}
Lucifer