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

发布于 2024-10-27 04:42:29 字数 2088 浏览 1 评论 0原文

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

白鸥掠海 2024-11-03 04:42:29

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

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

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.

雅心素梦 2024-11-03 04:42:29

您有两种选择:

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

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

You have two choices:

  1. Make the type public
  2. Avoid using reflection to do this, use generics instead.

If the safeguards were possible to avoid just because you didn't like them, there wouldn't be a need to have them at all.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文