2009-09-03 6 views
11

Celui-ci s'est avéré un peu difficile pour moi jusqu'à présent. Je me demande s'il est possible de taper cast un objet en utilisant un objet System.Type.Type Coulée d'un objet en utilisant un objet "Type" en C#

J'ai illustré ci-dessous ce que je veux dire:

public interface IDataAdapter 
{ 
    object Transform(object input); 
    Type GetOutputType(); 
} 

public class SomeRandomAdapter : IDataAdapter 
{ 
    public object Transform(object input) 
    { 
     string output; 

     // Do some stuff to transform input to output... 

     return output; 
    } 

    public Type GetOutputType() 
    { 
     return typeof(string); 
    } 
} 

// Later when using the above methods I would like to be able to go... 
var output = t.Transform(input) as t.GetOutputType(); 

Ce qui précède est une interface générique qui est la raison pour laquelle je me sers « objet » pour les types.

Répondre

8

La façon typique de le faire est d'utiliser les génériques, comme suit: Comme vous l'avez mentionné dans votre commentaire ci-dessous

public T2 Transform<T, T2>(T input) 
{ 
    T2 output; 

    // Do some stuff to transform input to output... 

    return output; 
} 

int number = 0; 
string numberString = t.Transform<int, string>(number); 

, les génériques sont très similaires aux modèles C++. Vous pouvez trouver le MSDN documentation for Generics here, et l'article "Differences Between C++ Templates and C# Generics (C# Programming Guide)" vous sera probablement utile. Enfin, je peux mal comprendre ce que vous voulez faire dans le corps de la méthode: je ne sais pas comment transformer un type arbitraire T en un autre type arbitraire T2, sauf si vous spécifiez des contraintes sur les types génériques. Par exemple, vous devrez peut-être spécifier qu'ils doivent tous deux implémenter une interface. Constraints on Type Parameters (C# Programming Guide) décrit comment faire cela en C#.

Modifier: Compte tenu de votre question révisée, je pense que this answer from Marco M. est correct (. Qui est, je pense que vous devriez utiliser le délégué Converter où vous essayez actuellement d'utiliser l'interface IDataAdapter)

+1

I ne l'a pas fait pour effacer dans l'exemple mais les deux méthodes sont dans une interface IDataAdapter. – Ryall

+0

Merci encore Jeff. – Ryall

+0

Pas de problème, et j'ai encore mis à jour ma réponse. –

2

Le ci-dessus est une interface générique qui est la raison pour laquelle je me sers « objet » pour les types

ne serait-il pas plus logique d'utiliser une interface générique réelle:

public U Transform<T, U>(T input) 
{ 
    string output; 

    return output; 
} 

U output = t.Transform(input) as U; 
+0

Ils ressemblent à des modèles de C++ - ne les ont pas encore couverts en C#. Merci! – Ryall

+0

Je suis un peu confus quant à la façon dont vous utilisez «U» en dehors du générique. Quelle portée avez-vous? – Ryall

+0

@Kelix: "U" serait votre type actuel, vous n'utiliseriez pas vraiment "U" comme ça.Regardez la réponse de @ Jeff et notez que son T2 est remplacé par "chaîne" et correspond de la même manière. –

3

Vous feriez mieux d'utiliser quelque chose comme le délégué Converter

public delegate TOutput Converter<TInput, TOutput>(TInput input); 

pour un exemple, consultez msdn

public static void Main() 
{ 
    // Create an array of PointF objects. 
    PointF[] apf = { 
     new PointF(27.8F, 32.62F), 
     new PointF(99.3F, 147.273F), 
     new PointF(7.5F, 1412.2F) }; 

    // Display each element in the PointF array. 
    Console.WriteLine(); 
    foreach(PointF p in apf) 
     Console.WriteLine(p); 

    // Convert each PointF element to a Point object. 
    Point[] ap = Array.ConvertAll(apf, 
     new Converter<PointF, Point>(PointFToPoint)); 

    // Display each element in the Point array. 
    Console.WriteLine(); 
    foreach(Point p in ap) 
    { 
     Console.WriteLine(p); 
    } 
} 

public static Point PointFToPoint(PointF pf) 
{ 
    return new Point(((int) pf.X), ((int) pf.Y)); 
} 
+0

Comment cela permet-il à un objet Type de lancer un autre objet? TInput et TOutput ne sont pas des objets et doivent être connus au moment de la compilation. – Despertar

7

Pourquoi faire compliqué, quand vous êtes sûr qu'il renvoie une chaîne ?

var output = t.Transform(input) as string; 

Si j'ai mal compris ce que vous dites, voici une autre façon

var output = Convert.ChangeType(t.Transform(input), t.GetOutputType()); 
+1

Parce que l'exemple est une interface - mise à jour maintenant. – Ryall

+0

Mise à jour, merci pour la réponse. – Ryall

+0

Je vais frapper 1 pour ça! J'aime l'idée de '' Convert.ChangeType() '' et de fournir le type de l'objet en tant que second argument afin qu'il soit changé en ce type. Je travaille sur une autre bibliothèque et j'espère que cela me sauvera la nuit. Merci @shahkalpesh –

2

C'est ce que je suis allé avec (à base de la structure IEnumerable):

public interface IDataAdapter 
{ 
    object Transform(object input); 
} 

public interface IDataAdapter<OutT, InT> : IDataAdapter 
{ 
    OutT Transform(InT input); 
} 

public class SomeClass : IDataAdapter<string, string> 
{ 
    public string Transform(string input) 
    { 
     // Do something... 
    } 

    public object Transform(object input) 
    { 
     throw new NotImplementedException(); 
    } 
} 
Questions connexes