views:

79

answers:

4

I have created this method which is an object factory:

public static T GetService<T>(T serviceInterface)
{
    if (serviceInterface.Equals(typeof(IMemberService)))
    {
        return (T)(object)new MemberService();
    }
    else if (serviceInterface.Equals(typeof(ILookupService)))
    {
        return (T)(object)new LookupService();
    }
    throw new ArgumentOutOfRangeException("No action is defined for service interface " + serviceInterface.Name);
}

Now, I would like to go further and eliminate the need for "serviceInterface" parameter, but my problem is - I don't know how to compare type parameter T to an interface: doing

T.Equals(typeof(ILookupService)) 

gives compiler error: 'T' is a 'type parameter', which is not valid in the given context.

Any ideas how could I compare a type parameter to an interface?

Thank you, Andrey

+3  A: 

You can use typeof(T) to get a Type object back which could replace the use of serviceInterface

For example

public static T GetService<T>()
{
    Type serviceInterface = typeof(T);
    if (serviceInterface.Equals(typeof(IMemberService)))
    {
        return (T)(object)new MemberService();
    }
    else if (serviceInterface.Equals(typeof(ILookupService)))
    {
        return (T)(object)new LookupService();
    }
    throw new ArgumentOutOfRangeException("No action is defined for service interface " + serviceInterface.Name);
}
JaredPar
Damn, now I'm embarrassed! Soooo simple! Thanks a bunch Jared!
Andrey
Sure, but will it ever equal an interface? If T represents the type of a concrete object, surely it won't equal an interface.
spender
@spender, The GetService method can just as equally be invoked with an interface. For example GetService<IFoo>();
JaredPar
OK agreed, but it gets smellier by the second
spender
@spender, this is actually a well defined and used pattern in MEF. `CompositionContainer` has this API and typically they are interface based.
JaredPar
To me it seems like a misappropriation of generics to start your generic method with checks for particular types/interfaces
spender
@spender I thought you were complaining about the call site, not the actual code. The actual code is also a common pattern though (think COM, or OLE IServiceProvider). Perahps not a great one, but an existing established one.
JaredPar
@spender - what's wrong with my code in particular? What would you propose to change?
Andrey
Andrey, there's probably nothing wrong. I just find it an unusual use of generics when the method branches according to the supplied generic type. In this situation I'd simply create two non-generic methods of fixed type. I appreciate (from Jared's comments) that this may not suit your purposes.
spender
I have to have one method - it's ultimately a service object factory, so I provide an interface and it will return a corresponding object. I figured that using generics in this case, even if unconventional, looks "nicer" in the code than returning an object and then casting to an interface
Andrey
A: 

Use typeof(T).

So,

typeof(T).Equals(typeof(ILookupService))
Kevin Montrose
A: 

Could the is operator be applicable here?

spender
+1  A: 
if (typeof(IMemberService).IsAssignableFrom(typeof(T)))
{}
else if (typeof(ILookupService).IsAssignableFrom(typeof(T)))
{}
Asad Butt
Combine this answer (`IsAssignableFrom`) with JaredPar's answer, and you'll have the complete solution.
fre0n
What's wrong with my original solution? I need to know if it the type passed matches exactly to the interface I compare to
Andrey