2011-03-29 11 views
2

Je crée une bibliothèque réutilisable pour Silverlight. La bibliothèque contient un type générique interne et j'ai besoin de créer une nouvelle instance de ce type générique, mais à un moment donné je n'ai pas d'argument de type générique disponible, seulement un objet System.Type qui représente l'argument générique. J'ai essayé de créer une instance en utilisant la réflexion, mais cela échoue, car cette classe est interne et Silverlight s'exécute effectivement en confiance partielle.Approbation partielle: comment instancier un type générique sans argument de type générique

Voici ce que j'ai essayé jusqu'à présent:

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

Ceci est mon type interne. Rien de fantaisie:

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

J'ai même essayé d'abuser de la struct Nullable<T> comme une usine pour la création d'une usine qui pourrait produire mon type interne. Cependant, par défaut Nullable<T> converties null références:

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

Comme vous pouvez l'imaginer, je ne veux pas faire ce type public, car il pollue mon API. Je suis actuellement à court d'idées. Quelles sont mes options? Que puis-je faire pour créer ce type interne?

Répondre

4

La troisième alternative consiste à prendre en charge une sorte de modèle d'usine qui contiendra une méthode pour instancier le type interne. Et vous pouvez exposer l'usine ou rendre public le type d'usine. Vous pouvez laisser la classe comme interne et vous pouvez appeler la méthode de TypeFactory via la réflexion. Je pense que votre TypeFactory devrait être publique, elle ne peut pas être interne.

+0

Je ne suis pas sûr de vous suivre. Pouvez-vous donner un exemple? – Steven

+0

@Akash: Merci pour l'exemple, mais cela ne fera malheureusement pas l'affaire, car je n'ai pas de 'T' générique, juste un 'System.Type' représentant ce' T'. – Steven

+0

D'où vient le T? Ne pouvez-vous pas fournir un délégué d'usine ou quelque chose à la place/à côté? –

3

Vous avez deux choix:

  1. publique Réglez les paramètres
  2. Évitez d'utiliser la réflexion pour ce faire, utilisez génériques à la place.

Si les sauvegardes étaient possibles à éviter simplement parce que vous ne les aimiez pas, il n'y aurait pas besoin de les avoir du tout.

+0

Merci pour votre réponse. Je n'essaie pas d'éviter le mécanisme de sécurité Silverlight, ne vous inquiétez pas :-). J'avais peur que ce soient mes options. – Steven

+0

Toutes mes excuses si cela vous semblait implicite, mais oui, ce sont vos choix, en raison du système de sécurité de Silverlight. Je suppose que créer une application hors navigateur dans Silverlight qui s'exécute avec une confiance totale n'est pas une option? –

+0

L'exécution en toute confiance n'est pas une option. C'est une bibliothèque réutilisable, et restreindre mes utilisateurs pour qu'ils l'exécutent en toute confiance est simplement une restriction trop grande. – Steven

Questions connexes