2009-08-07 6 views
1

Possible en double:
Create instance of generic type?C# Generics aide - comment passer params à nouveau T()

Comment puis-je passer un à un contstructor param générique?

public class Payment<T> where T: HostFunctionContext, IClaimPayment, new() 
{ 

    public IResultEntity Display(MyUser user, string claim, int? cert) 
    { 
     **HostFunctionContext func = new T(user) as HostFunctionContext;** <~doesn't compile   
     IClaimPayment payment = new T(); 
     payment.ClaimNumber = claimNumber; 
     payment.CertificateSequence = certSequence; 

     return payment.DisplayEntity(); 

    } 

}

public sealed partial class CardPayment : HostFunctionContext 
{ 
    public CardPayment(MyUser user) : base(user) { } 

}

constructeur

pour HostFunctionContext abstrait

public HostFunctionContext(MyUser user) { 

     _hostConnection = HostConnectionAssembler.GetHostConnection(); 
     _functionParams = FunctionParamsAssembler.GetFunctionParams(); 
     if (user != null) { 
      _hostConnection.Login = user.Login; 

     } 
    } 

Je dois passer à l'utilisateur de la baseclass T. Comment puis-je faire cela? Est-ce que je crée un constructeur sans paramètre, puis une propriété de type MyUser, puis sur l'ensemble de cette propriété, je le pousse vers la baseclass? La baseclass abstraite n'a pas de propriété myUser et pas de constructeur sans paramètre. Je suis vraiment coincé ici.

Merci pour toute aide, ~ ck

+0

dupe: http://stackoverflow.com/questions/731452/create-instance-of-generic-type – meandmycode

Répondre

3

Le nouveau() mot-clé, par définition, limite votre paramètre générique pour être un type de référence avec un public, constructeur parameterless. Lorsque vous instanciez un "nouveau T()", il doit utiliser la réflexion pour en créer une instance.

Vous pouvez utiliser un modèle d'usine pour créer vos objets au lieu d'essayer de le faire via un constructeur générique. Vous pouvez passer le type dans l'usine et faire en sorte que la logique d'usine vous renvoie le type d'objet correct, initialisé avec l'utilisateur.

+0

Pourquoi un compilateur doit-il utiliser la réflexion? –

+0

Qui a dit quelque chose au sujet du compilateur? Voir ici pour une bonne explication: http://stackoverflow.com/questions/367577/why-does-the-c-compiler-emit-activator-createinstance-when-calling-new-in-with-a – womp

+0

@David B : Parce qu'il n'y a rien construit dans IL pour exprimer "construire une nouvelle instance de ce paramètre type en utilisant un constructeur sans paramètre". –

0

Je n'ai pas essayé cela moi-même mais sûrement (pour le bon type) vous pourriez simplement utiliser les propriétés sur l'interface pour obtenir ce dont vous avez besoin?

T foo = new T{ Prop1="BAR", Prop2="BAZ" } 
+0

T devrait exposer ces propriétés via une interface fournie dans le cadre des contraintes, mais cela pourrait fonctionner. –

+0

Oh oui, "utiliser les propriétés sur l'interface" - Je suppose que le OP IClaimPayment a ceux-ci ou peut être étendu pour les avoir. – annakata

0

Si vous ne disposez pas d'un constructeur sans paramètre de base, vous ne pourrez pas utiliser de génériques de ce type. Une option consiste à exiger que le constructeur de paiement pour recevoir des « instructions » pour savoir comment construire son T, par l'intermédiaire d'un délégué:

public class Payment<T> where T: HostFunctionContext, IClaimPayment 
{ 
    private Func<MyUser, T> ContextBuilder { get; set; } 
    public Payment(Func<MyUser, T> contextBuilder) 
    { 
     ContextBuilder = contextBuilder; 
    } 

    public IResultEntity Display(MyUser user, string claim, int? cert) 
    { 
     T context = ContextBuilder(user); 

     IClaimPayment payment = context as IClaimPayment; 
     payment.ClaimNumber = claimNumber; 
     payment.CertificateSequence = certSequence; 

     return payment.DisplayEntity(); 
    } 
} 

// Usage: 
var MyCreditPayment = new Payment<CreditPayment>(user => new CreditPayment(user)); 

Il existe d'autres modèles pour y parvenir, mais en fin de compte, vous allez avoir besoin d'un moyen de encapsuler comment votre contexte est créé.