¿Cómo convertir un objeto a su tipo real?


120

Si tengo:

void MyMethod(Object obj) {   ...   }

¿Cómo puedo convertir obja cuál es su tipo real?


2
¿Se conoce el tipo en tiempo de compilación?
psubsee2003

1
¿Y qué espera lograr con esto? Díganos qué está tratando de lograr, en lugar de cómo espera lograrlo.
Jon Skeet

@JonSkeet: Quiero poder llamar a una función desde el objeto. Actualmente obj.MyFunction();no se compila, aunque sé que el objeto real tiene esa función.
Paul Lassiter

@ psubsee2003: no, no lo hace, porque es una referencia de objeto que se pasa por interoperabilidad.
Paul Lassiter

3
@PaulLassiter: Si no conoce el tipo, ¿qué declara el MyFunctionmétodo?
Jon Skeet

Respuestas:


194

Si conoce el tipo real, simplemente:

SomeType typed = (SomeType)obj;
typed.MyFunction();

Si no conoce el tipo real, entonces: no realmente, no. En su lugar, tendría que usar uno de:

  • reflexión
  • implementando una interfaz conocida
  • dinámica

Por ejemplo:

// reflection
obj.GetType().GetMethod("MyFunction").Invoke(obj, null);

// interface
IFoo foo = (IFoo)obj; // where SomeType : IFoo and IFoo declares MyFunction
foo.MyFunction();

// dynamic
dynamic d = obj;
d.MyFunction();

1
¿Cuál es la sintaxis equivalente en Swift?
Nagendra Rao

1
No importa, se encuentra aspara encasillamiento y type(of: ClassName)función para verificar el tipo de instancia.
Nagendra Rao

42

No creo que pueda (no sin reflexión), también debe proporcionar un tipo a su función:

void MyMethod(Object obj, Type t)
{
    var convertedObject = Convert.ChangeType(obj, t);
    ...
}

UPD :

Esto puede funcionar para usted:

void MyMethod(Object obj)
{
    if (obj is A)
    {
        A a = obj as A;
        ...
    } 
    else if (obj is B)
    {
        B b = obj as B;
        ...
    }
}

4
Esta es realmente una respuesta inútil, que no merece votos a favor. La reflexión de un objeto de tipo object no producirá el "tipo real" del objeto, como lo pide OP. Además, su lógica de MyMethod es defectuosa porque obj puede ser de tipo A y también puede ser de tipo B. Su lógica no proporciona el "tipo real" (como lo solicitó OP); proporciona un tipo compatible, y no necesariamente el tipo deseado en eso.
Jazimov

utilice obj.GetType (). Eso definitivamente devolverá su tipo real.
JSON

3

¿Qué tal JsonConvert.DeserializeObject (object.ToString ());


Ésta no es una respuesta satisfactoria. La pregunta de OP no tiene nada que ver con Json o serialización.

@ user12637955 esta es en realidad una respuesta funcional, pero tiene una mayor complejidad, debido al encajonamiento y desempaquetado, es decir, objeto -> ToString () -> al tipo concreto. Para ser más preciso, debería verse así:var myType = JsonConvert.DeserializeObject<MyType>(object.ToString());
Coca Cola

1

En mi caso, AutoMapper funciona bien.

AutoMapper puede mapear hacia / desde objetos dinámicos sin ninguna configuración explícita:

public class Foo {
    public int Bar { get; set; }
    public int Baz { get; set; }
}
dynamic foo = new MyDynamicObject();
foo.Bar = 5;
foo.Baz = 6;

Mapper.Initialize(cfg => {});

var result = Mapper.Map<Foo>(foo);
result.Bar.ShouldEqual(5);
result.Baz.ShouldEqual(6);

dynamic foo2 = Mapper.Map<MyDynamicObject>(result);
foo2.Bar.ShouldEqual(5);
foo2.Baz.ShouldEqual(6);

De manera similar, puede mapear directamente desde diccionarios a objetos, AutoMapper alineará las claves con los nombres de las propiedades.

más información https://github.com/AutoMapper/AutoMapper/wiki/Dynamic-and-ExpandoObject-Mapping


1

Puede que este método no sea el más eficaz, pero es sencillo y funciona.

Realiza dos operaciones: primero llama a .ToString () que es básicamente una serialización, y luego la deserialización usando Newtonsoft nuget (que debe instalar).

public T Format<T>(Object obj) =>
    JsonConvert.DeserializeObject<T>(obj.ToString());

Debe describir su respuesta brevemente para los futuros lectores.
Suraj Kumar

0

Si su MyFunction()método está definido solo en una clase (y sus descendientes), intente

void MyMethod(Object obj) 
{
    var o = obj as MyClass;
    if (o != null)
        o.MyFunction();
}

Si tiene una gran cantidad de clases no relacionadas que definen la función que desea llamar, debe definir una interfaz y hacer que sus clases definan esa interfaz:

interface IMyInterface
{
    void MyFunction();
}

void MyMethod(Object obj) 
{
    var o = obj as IMyInterface;
    if (o != null)
        o.MyFunction();
}

0

Conviértalo a su tipo real si ahora el tipo, por ejemplo, está orientado desde la clase llamada abc. Puede llamar a su función de esta manera:

(abc)(obj)).MyFunction();

si no conoce la función, se puede hacer de otra manera. No siempre es fácil. Pero puedes encontrarlo de alguna manera por su firma. Si este es tu caso, háznoslo saber.


-1

Transmitir al tipo real es fácil:

void MyMethod(Object obj) {
    ActualType actualyType = (ActualType)obj;
}

8
Esto es ilógico. En realidad, no conoce el tipo real. ¿Cómo se supone que vas a hacer eso?
Allen Linatoc

-2
Implement an interface to call your function in your method
interface IMyInterface
{
 void MyinterfaceMethod();
}

IMyInterface MyObj = obj as IMyInterface;
if ( MyObj != null)
{
MyMethod(IMyInterface MyObj );
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.