【问题标题】:Partial trust: How to instantiate a generic type without a generic type argument部分信任:如何在没有泛型类型参数的情况下实例化泛型类型
【发布时间】:2011-03-29 18:29:50
【问题描述】:

我正在为 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&lt;T&gt; 结构作为工厂来创建可以生成我的内部类型的工厂。但是,默认的 Nullable&lt;T&gt; 会被转换为空引用:

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。我目前没有想法。我有哪些选择?我可以做些什么来创建这种内部类型?

【问题讨论】:

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


    【解决方案1】:

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

    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 应该是公开的,不能是内部的。

    【讨论】:

    • 我不确定我是否关注你。能举个例子吗?
    • @Akash:感谢您提供的示例,但不幸的是,这并不能解决问题,因为我没有通用的T,只有一个代表TSystem.Type。跨度>
    • T 是从哪里来的?您不能提供工厂代表或其他东西吗?
    • @Lasse:这是@Akash 的问题还是我的问题?如果是为了我;我不确定我是否跟随你。你能详细说明一下吗?
    • @Steven,你必须使用反射来调用这个方法,我已经向你展示了这个例子。
    【解决方案2】:

    你有两个选择:

    1. 公开类型
    2. 避免使用反射来执行此操作,而是使用泛型。

    如果仅仅因为你不喜欢这些保护措施就可以避免,那么根本就没有必要拥有它们。

    【讨论】:

    • 感谢您的回复。我不是想避免 Silverlight 安全机制,别担心 :-)。我担心这些是我的选择。
    • 抱歉,如果听起来我暗示你是,但是是的,由于 Silverlight 中的安全系统,这些是你的选择。我假设在 Silverlight 中创建一个以完全信任运行的浏览器外应用程序不是一种选择?
    • 完全信任运行不是一种选择。它是一个可重用的库,限制我的用户完全信任地运行它只是一个太大的限制。
    猜你喜欢
    • 1970-01-01
    • 2022-10-13
    • 1970-01-01
    • 2013-10-03
    • 2011-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多