Reputation: 2815
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.
Upvotes: 2
Views: 335
Reputation: 178820
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.
Upvotes: 5
Reputation: 10280
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>");
}
}
Upvotes: 1
Reputation: 100059
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);
Upvotes: 1