Pregunta

Estoy creando una biblioteca reutilizable para Silverlight.La biblioteca contiene un tipo genérico interno y necesito crear una nueva instancia de este tipo genérico, pero en un punto no tengo un argumento de tipo genérico disponible, solo un objeto System.Type que representa el argumento genérico.Intenté crear una instancia utilizando la reflexión, pero esto falla, porque esta clase es interna y Silverlight se ejecuta de manera efectiva en confianza parcial.

Aquí está lo que intenté hasta ahora:

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;
}

Este es mi tipo interno.Nada de lujo:

internal class InternalGenericType<T> : INonGenericInterface
    where T : class
{
    public InternalGenericType()
    {
    }
}

Incluso intenté abusar de la estructura de Nullable<T> como una fábrica para crear una fábrica que podría producir mi tipo interno.Sin embargo, generalmente predeterminado se convierte en referencias nulas:

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>();
       }
   }
}

Como puedes imaginar, no quiero hacer públicos este tipo, porque contaminaría mi API.Actualmente estoy fuera de las ideas.¿Cuáles son mis opciones?¿Qué puedo hacer para crear este tipo interno?

¿Fue útil?

Solución

La tercera alternativa es para admitir algún tipo de patrón de fábrica que contendrá un método para inscanciar el tipo interno.Y puede exponer fábrica o hacer públicos de tipo de fábrica.

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

Puede dejar la clase como interna y puede invocar el método de TypeFactory a través de la reflexión.

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

Creo que su tipogría debe ser público, no puede ser interno.

Otros consejos

Tienes dos opciones:

  1. HACER EL TIPO PÚBLICO
  2. Evite usar la reflexión para hacer esto, use los genéricos en su lugar.

    Si las salvaguardas fueron posibles para evitar solo porque no les gustó, no habría necesidad de tenerlos en absoluto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top