I'm creating a reusable library for Silverlight. The library contains an internal generic type and I need to create a new instance of this generic type, but I at one point I don't have a generic type argument available, only a System.Type
object that represents the generic argument. I tried to create an instance using reflection, but this fails, because this class is internal and Silverlight effectively runs in partial trust.
Here is what I tried so far:
private INonGenericInterface CreateInstance(Type type)
{
// Activator.CreateInstance fails
var instance = Activator.CreateInstance(
typeof(InternalGenericType<>).MakeGenericType(type));
// Invoking the default constructor of that type fails.
var producer = typeof(InternalGenericType<>)
.MakeGenericType(type)
.GetConstructor(new Type[0])
.Invoke(null);
return (INonGenericInterface)producer;
}
This is my internal type. Nothing fancy:
internal class InternalGenericType<T> : INonGenericInterface
where T : class
{
public InternalGenericType()
{
}
}
I even tried abusing the Nullable<T>
struct as a factory for creating a factory that could produce my internal type. However, default Nullable<T>
get converted to null references:
internal static class InternalGenericTypeFactory
{
public static INonGenericInterface Create(Type serviceType)
{
var nullType = typeof(Nullable<>).MakeGenericType(
typeof(Factory<>).MakeGenericType(serviceType));
// Activator succesfully creates the instance, but .NET
// automatically converts default Nullable<T>s to null.
object nullInstance = Activator.CreateInstance(nullType);
var getValueMethod =
nullType.GetMethod("GetValueOrDefault", new Type[0]);
// Invoke fails, because nullInstance is a null ref.
var factory = getValueMethod.Invoke(nullInstance, null);
return ((IFactory)factory).CreateInstance();
}
internal interface IFactory
{
INonGenericInterface CreateInstance();
}
internal struct Factory<T> : IFactory where T : class
{
public INonGenericInterface CreateInstance()
{
return new InternalGenericType<T>();
}
}
}
As you can imagine, I don't want to make this type public, because it would pollute my API. I'm currently out of ideas. What are my options? What can I do to create this internal type?
Third alternative is to support some sort of factory pattern which will contain a method to instanciate internal type. And you can expose factory or make factory type public.
public class TypeFactory
{
public static object Create<T>()
{
return new MyInternalType<T>();
}
}
You can leave class as internal and you can invoke TypeFactory's method via reflection.
public object CreateType(System.Type type)
{
Type typeFactory = typeof(TypeFactory);
MethodInfo m = typeFactory.GetMethod("Create").MakeGenericMethod(type);
return m.Invoke(null, null);
}
I think your TypeFactory should be public, it can not be internal.