tags:

views:

94

answers:

4

I could very will be imagining things, but I seem to recall in Java that I can declare a field or parameter as such:

public class BarHandler{

    public Class<? extends Foo> fooType;

    public ProcessedBar Process(string xml){
        Foo foo = fooType.GetInstance();
        return foo.process(xml)
    }
}

This can be useful for factory style systems where you have to be able to generate new instances of the type in question for example.

I am trying to figure out if there is an analog to this in C#, or if possibly this is just something that is available within Java.

+5  A: 

Yes, see generic constraints. The equivalent to your example would be:

public class SomeClass<T>
    where T : Foo
{
    private T fooType;
}

EDIT AFTER YOUR EDIT: I believe you're referring to wildcards, in which case you should read about covariance and contravariance with respect to generics.

HTH,
Kent

Kent Boogaart
As I said with TreDubZedd, I did find the generic constraints item already and doing it on a class level I get. I am looking specifically at the type class and a way to limit down the types I am willing to store.
Matt
Edited accordingly.
Kent Boogaart
+1  A: 
public class GenericClass<T> where T : Foo
TreDubZedd
Right idea wrong level. I found how to do it with a generic class, but I want to do it with a parameter or field of a type. I am expanding my example above to explain.
Matt
+1  A: 

You could use a very simple wrapper for this annotation and a cheap runtime check:

public sealed class Type<T>
{
    public Type(Type type)
    {
        if (type == null)
            throw new ArgumentNullException("type");
        if (!typeof(T).IsAssignableFrom(type))
            throw new ArgumentException(string.Format("The specified type must be assignable to '{0}'.", typeof(T).FullName));

        this.Value = type;
    }

    public Type Value
    {
        get;
        private set;
    }
}

Use Activator.CreateInstance to actually create an instance of the type. Suppose FooDerived is derived from Foo.

Type<Foo> fooType = new Type<Foo>(typeof(FooDerived));
Activator.CreateInstance(fooType.Value);
280Z28
+1  A: 

Here's a variation of 280Z28's answer. I've renamed the "Type" class to "Factory", since in my version it exposes a GetInstance method instead of a Value property of type Type. This uses 2 generic parameters and generic constraints to enforce the rules that were in the original answer's constructor for the Type class.

public abstract class Factory<T>
{
    public abstract T GetInstance();
}

public sealed class IoCFactory<T, TDerived> : Factory<T>
    where TDerived : T // compiler enforces that TDerived derives from T
{
    public override T GetInstance()
    {
        // TODO: retrieve instance of TDerived from IoC container such as Spring.NET, StructureMap, Unity, etc.
        throw new NotImplementedException();
    }
}

public sealed class ActivatorFactory<T, TDerived> : Factory<T>
    where TDerived : T, new() // compiler enforces that TDerived derives from T and that it has a parameterless constructor
{
    public override T GetInstance()
    {
        return Activator.CreateInstance<TDerived>();
    }
}

public class BarHandler
{
    public Factory<Foo> fooFactory { get; set; }

    public ProcessedBar Process(string xml)
    {
        Foo foo = fooFactory.GetInstance();
        return foo.Process(xml);
    }
}

class Program
{
    static void Main(string[] args)
    {
        BarHandler handler = new BarHandler();

        handler.fooFactory = new ActivatorFactory<Foo, Bar>();

        var processedResult = handler.Process("<bar>Yar!</bar>");
    }
}
Dr. Wily's Apprentice