Domanda

Sto creando una biblioteca riutilizzabile per Silverlight.La biblioteca contiene un tipo generico interno e ho bisogno di creare una nuova istanza di questo tipo generico, ma a un punto non ho un argomento tipo generico disponibile, solo un oggetto System.Type che rappresenta l'argomento generico.Ho provato a creare un'istanza usando la riflessione, ma questo fallisce, perché questa classe è interna e Silverlight esegue efficacemente in trust parziale.

Ecco cosa ho provato finora:

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

Questo è il mio tipo interno.Niente di fantasia:

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

Ho persino provato abusare della struttura Nullable<T> come fabbrica per creare una fabbrica che potrebbe produrre il mio tipo interno.Tuttavia, Nullable<T> predefinito viene convertito in riferimenti 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>();
       }
   }
}
.

Come puoi immaginare, non voglio rendere questo tipo pubblico, perché inquinerebbe la mia API.Sono attualmente senza idee.Quali sono le mie opzioni?Cosa posso fare per creare questo tipo interno?

È stato utile?

Soluzione

La terza alternativa è supportare una sorta di modello di fabbrica che conterrà un metodo per installare il tipo interno.E puoi esporre la fabbrica o rendere pubblico il tipo di fabbrica.

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

È possibile lasciare la classe come interna e puoi richiamare il metodo di tipografo tramite la riflessione.

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

Penso che il tuo tipo di tipici debba essere pubblico, non può essere interno.

Altri suggerimenti

Hai due scelte:

    .
  1. Rendi il tipo pubblico
  2. Evita di usare la riflessione per farlo, usa invece i generici.

    Se le salvaguardie fossero possibili per evitare solo perché non ti piacciono, non ci sarebbe bisogno di averli affatto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top