部分信任:如何在没有泛型类型参数的情况下实例化泛型类型

时间:2011-03-29 18:29:51

标签: c# .net silverlight reflection partial-trust

我正在为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>结构作为工厂来创建可以生成内部类型的工厂。但是,默认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。我目前没有想法。我有什么选择?如何创建此内部类型?

2 个答案:

答案 0 :(得分:4)

第三种选择是支持某种工厂模式,它将包含一种实现内部类型的方法。您可以公开工厂或公开工厂类型。

public class TypeFactory
{
    public static object Create<T>()
    {
         return new MyInternalType<T>();
    }
}

您可以将类保留为内部类,也可以通过反射调用TypeFactory的方法。

public object CreateType(System.Type type)
{
    Type typeFactory = typeof(TypeFactory);
    MethodInfo m = typeFactory.GetMethod("Create").MakeGenericMethod(type);
    return m.Invoke(null, null);
}

我认为你的TypeFactory应该是公开的,它不能是内部的。

答案 1 :(得分:3)

您有两种选择:

  1. 将类型设为公开
  2. 避免使用反射来执行此操作,而是使用泛型。
  3. 如果保护措施可以避免仅仅是因为你不喜欢它们,就根本不需要它们。