部分信托:如何在没有泛型类型参数的情况下实例化泛型类型
-
14-11-2019 - |
题
我正在为Silverlight创建一个可重用的库。该库包含一个内部泛型类型,我需要创建这个泛型类型的新实例,但我在一个点上我没有一个泛型类型参数可用,只有一个 System.Type
表示泛型参数的对象。我试图使用反射创建一个实例,但这失败了,因为这个类是内部的,Silverlight有效地在部分信任中运行。
这是我到目前为止所尝试的:
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;
}
这是我的内部类型。没什么花哨的:
internal class InternalGenericType<T> : INonGenericInterface
where T : class
{
public InternalGenericType()
{
}
}
我甚至试图滥用 Nullable<T>
struct作为一个工厂,用于创建一个可以产生我的内部类型的工厂。但是,默认 Nullable<T>
获取转换为空引用:
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>();
}
}
}
你可以想象,我不想让这种类型公开,因为它会污染我的API。我现在没主意了。我有什么选择?我可以做些什么来创建这个内部类型?
解决方案
第三种选择是支持某种工厂模式,它将包含一个实例化内部类型的方法。您可以公开factory或将factory类型公开。
public class TypeFactory
{
public static object Create<T>()
{
return new MyInternalType<T>();
}
}
您可以将class保留为internal,并且可以通过反射调用TypeFactory的方法。
public object CreateType(System.Type type)
{
Type typeFactory = typeof(TypeFactory);
MethodInfo m = typeFactory.GetMethod("Create").MakeGenericMethod(type);
return m.Invoke(null, null);
}
我认为你的TypeFactory应该是公开的,它不能是内部的。
其他提示
你有两个选择:
- 使类型公开
- 避免使用反射来做到这一点,而是使用泛型。
如果保障措施可以避免,只是因为你不喜欢他们,就没有必要有他们在所有。
不隶属于 StackOverflow