2009-09-03 18 views
11

Este ha demostrado ser un poco complicado para mí hasta ahora. Me pregunto si es posible escribir lanzar un objeto usando un objeto System.Type.Tipo Casting an Object utilizando un objeto "Type" en C#

he ilustrado por debajo de lo que quiero decir:

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

Lo anterior es una interfaz genérica que es por eso que estoy usando "objeto" para los tipos.

Respuesta

8

La forma típica de hacer esto es utilizar los genéricos, así:

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

Como se mencionó en su comentario a continuación, los genéricos son muy similares a C++ plantillas. Puede encontrar el MSDN documentation for Generics here, y el artículo "Differences Between C++ Templates and C# Generics (C# Programming Guide)" probablemente sea útil.

Finalmente, podría estar entendiendo mal lo que quiere hacer dentro del cuerpo del método: no estoy seguro de cómo va a transformar un tipo arbitrario T en otro tipo arbitrario T2, a menos que especifique restricciones en los tipos genéricos. Por ejemplo, puede que necesite especificar que ambos tienen que implementar alguna interfaz. Constraints on Type Parameters (C# Programming Guide) describe cómo hacer esto en C#.

Editar: Dada su pregunta revisada, creo this answer from Marco M. es correcto (. Es decir, creo que se debe utilizar el delegado Converter donde está actualmente tratando de utilizar la interfaz de IDataAdapter)

+1

I no dejó claro en el ejemplo pero los dos métodos están dentro de una interfaz IDataAdapter. – Ryall

+0

Gracias de nuevo Jeff. – Ryall

+0

No hay problema, y ​​he actualizado mi respuesta un poco más. –

2

El anterior es una interfaz genérica que es por eso que estoy usando "objeto" para los tipos

¿no tendría más sentido usar una interfaz genérica real:

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

    return output; 
} 

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

Parecen Plantillas de C++; aún no las han cubierto en C#. ¡Gracias! – Ryall

+0

Estoy un poco confundido sobre cómo está usando 'U' fuera del genérico. ¿Qué alcance le dan? – Ryall

+0

@Kelix: "U" sería tu tipo real, realmente no usarías "U" así.Mire la respuesta de @ Jeff y observe que su T2 se reemplaza por "cadena" y coincide de la misma manera. –

3

Usted es mejor usar algo como el delegado del convertidor

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

por ejemplo, echa un vistazo a 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

¿Cómo esto permite que un objeto Type arroje otro objeto? TInput y TOutput no son objetos y deben conocerse en tiempo de compilación. – Despertar

7

Por qué hacerlo complicado, cuando esté seguro de que devuelve una cadena ?

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

Si he entendido bien lo que está diciendo, aquí es una forma más

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

Porque el ejemplo es una interfaz, actualizándose ahora. – Ryall

+0

Actualizado, gracias por la respuesta. – Ryall

+0

¡Voy a golpear 1 para esto! Me gusta la idea de '' Convert.ChangeType() '' y proporcionar el tipo del objeto como segundo argumento, por lo que se cambiará a ese tipo. Estoy trabajando en otra biblioteca y espero que esto me salve la noche. Gracias @shahkalpesh –

2

Esto es lo que he ido con (sobre la base de la estructura de 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(); 
    } 
} 
Cuestiones relacionadas