2011-04-12 10 views
1

J'ai écrit une classe générique et je veux créer son instance à partir d'une méthode statique. Le problème est que je ne peux pas créer une instance générique de l'objet. Je sais que cela semble confus et il est préférable de montrer le code. Je ne suis pas sûr si cela est possible du tout ... mais on dirait que c'est une exigence de conception d'objet trivial. Des idées? Merci!Retour instance de type générique

UPD: J'utilise .NET 4.0. Cela fait-il une différence? :)

UPD2: En regardant le problème maintenant, je vois que c'est une question idiote. Et il est impossible de retourner de tels objets "génériques".

+0

Il est tout à fait impossible de mettre 'T' à l'intérieur de la méthode. Pensez: Comment pourriez-vous appeler une telle méthode? – SLaks

+0

var paramètre = Parameter.FromXml (élément); ? :) –

+0

Bien sûr, vous pouvez plonger dans le domaine de la dynamique, mais je ne plongerais pas dans celui-ci pour rapidement;) – Polity

Répondre

1

Crée une classe de base non générique et en hérite la classe générique (ils peuvent avoir le même nom et ne différer que par le type générique). Dans la classe de base non générique, créez des instances génériques dans votre méthode statique (qui renvoie la classe de base non générique comme résultat). Vous pouvez ensuite convertir ceci en type générique auquel vous vous attendez.

public abstract class Parameter { 
    public static Parameter FromXml(XElement xElement) { 
    ... 
    } 

    public string Name { get; set; } 

    public abstract XElement ToXml(); 
} 

public class Parameter<T>: Parameter { 
    public T Value { get; set; } 

    public override XElement ToXml() { 
    ... 
    } 
} 

Il n'y a pas vraiment une autre façon de le faire, puisque dans votre échantillon du type de T est spécifié avant la méthode statique fonctionne.

+0

Merci! J'ai pensé à ça. Êtes-vous sûr qu'il n'y a pas d'autre moyen, étant donné que j'utilise .NET 4.0? –

+0

Oui, car cela violerait le contrat, quelle que soit la version que vous utilisez: dans votre code, le paramètre .FromXml() '* doit * renvoyer un' Parameter 'puisque c'est le type de retour déclaré pour cette méthode. – Lucero

0

Ceci fonctionne pour les classes personnalisées mais peut ne pas fonctionner pour les types de valeurs. Jetez un oeil à This Post pour voir comment cela fonctionne pour les types de tas.

+0

Comment cela se rapporte-t-il vraiment à la question ici? – Lucero

0

Comme indiqué par SLaks, c'est impossible. Pensez-y de cette façon,

Parameter<???> value = Parameter<???>.FromXml(...); 

Comment allez-vous résoudre jamais ce que les questionmarks devraient être quand cela dépend du contenu du XmlElement?

Vous devez utiliser une classe commune qui capture la valeur en tant qu'objet et expose les informations de type.

1

Le problème est: T est évalué au moment de la compilation. Le compilateur n'a aucune chance de savoir à quel type votre type 'sType' va évaluer au moment de l'exécution. De plus, dans l'assemblage compilé, aucun générique n'existe plus. Par conséquent, afin de construire un type à l'exécution, basé sur une condition qui ne peut être évaluée qu'à l'exécution, vous devrez présenter un type concret au compilateur de toute façon. Donc, quelque part, vous pouvez décider de votre type de retour dans un si .. autre cascade comme ça:

if (sType is String) 
    return new Parameter<String>() 

else if (sType is double) 
    return new Parameter<double>() 
... 

Cela peut être placé à l'intérieur d'une classe de fabrique ou juste à côté de la classe XElement, je suppose. Afin de pouvoir retourner Parameter par exemple, vous pouvez utiliser une interface (ou une classe de base commune, comme dans une autre réponse), qui peut représenter toutes les variantes de Parameter. C'est la raison pour laquelle la méthode, qui analyse le Xml IMO, est mieux placée en dehors de Parameter.

De plus, comme il semble, vous êtes cert de « désérialisation » à partir de XML, pensez à utiliser certaines fonctionnalités dégivreur/sérialiseur;)

+0

"De plus, dans l'assemblage compilé, aucun générique n'existe plus." - Je pense que vous mélangez les effacements de Java avec les génériques (réels) .NET. Dans .NET, chaque type générique forme un type distinct pour chaque combinaison de types génériques utilisés comme arguments de type. Vous pouvez les créer lors de l'exécution en utilisant le 'MakeGenericType()' sur le 'Type' générique ouvert (par exemple dans cet exemple' typeof (Paramètre <>). MakeGenericType (typeof (string)) 'donnerait le même type à l'exécution que' typeof (paramètre ) '). – Lucero

Questions connexes