Como converter Objeto em seu tipo real?


120

Se eu tiver:

void MyMethod(Object obj) {   ...   }

Como posso converter o objque é seu tipo real?


2
O tipo é conhecido em tempo de compilação?
psubsee2003

1
E o que você espera realizar com isso? Diga-nos o que você está tentando alcançar, em vez de como espera alcançá-lo.
Jon Skeet,

@JonSkeet: Eu quero poder chamar uma função do objeto. Atualmente obj.MyFunction();não compila, embora eu saiba que o objeto real tem essa função.
Paul Lassiter,

@ psubsee2003: não, não faz, porque é uma referência de objeto sendo passada via interoperabilidade.
Paul Lassiter

3
@PaulLassiter: Se você não conhece o tipo, o que declara o MyFunctionmétodo?
Jon Skeet,

Respostas:


194

Se você souber o tipo real, basta:

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

Se você não conhece o tipo real, então: não realmente, não. Você teria que usar um dos seguintes:

  • reflexão
  • implementar uma interface bem conhecida
  • dinâmico

Por exemplo:

// 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
Qual é a sintaxe equivalente em Swift?
Nagendra Rao,

1
Nevermind, encontrado aspara typecasting e type(of: ClassName)função para verificar o tipo de instância.
Nagendra Rao,

42

Eu não acho que você pode (não sem reflexão), você deve fornecer um tipo para sua função também:

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

UPD :

Isso pode funcionar para você:

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 é realmente uma resposta inútil, não merece votos positivos. A reflexão de um objeto do tipo objeto não produzirá o "tipo real" do objeto, conforme solicitado pelo OP. Além disso, sua lógica MyMethod é falha porque obj pode ser do tipo A e também pode ser do tipo B. Sua lógica não fornece o "tipo real" (conforme solicitado pelo OP) - fornece um tipo compatível, e não necessariamente o tipo desejado nisso.
Jazimov

use obj.GetType (). Isso definitivamente retornará seu tipo real.
JSON

3

Que tal JsonConvert.DeserializeObject (object.ToString ());


Esta não é uma resposta satisfatória. A pergunta de OP não tem nada a ver com Json ou serialização.

@ user12637955 esta é na verdade uma resposta funcional, mas tem maior complexidade, devido ao boxing e unboxing, ou seja, objeto -> ToString () -> ao tipo concreto. Para ser mais preciso, deve ser assim:var myType = JsonConvert.DeserializeObject<MyType>(object.ToString());
Coca

1

No meu caso, o AutoMapper funciona bem.

O AutoMapper pode mapear de / para objetos dinâmicos sem qualquer configuração 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);

Da mesma forma, você pode mapear diretamente dos dicionários para os objetos, o AutoMapper alinhará as chaves com os nomes das propriedades.

mais informações https://github.com/AutoMapper/AutoMapper/wiki/Dynamic-and-ExpandoObject-Mapping


1

Este método pode não ser o mais eficiente, mas é simples e faz o trabalho.

Ele executa duas operações: primeiro chama .ToString (), que é basicamente uma serialização, e depois a desserialização usando o nuget Newtonsoft (que você deve instalar).

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

Você deve descrever sua resposta brevemente para os futuros leitores.
Suraj Kumar

0

Se o seu MyFunction()método é definido apenas em uma classe (e seus descendentes), tente

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

Se você tem um grande número de classes não relacionadas definindo a função que deseja chamar, você deve definir uma interface e fazer suas classes definirem essa interface:

interface IMyInterface
{
    void MyFunction();
}

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

0

Converta-o em seu tipo real se você agora o tipo, por exemplo, é orientado a partir de uma classe chamada abc. Você pode chamar sua função desta forma:

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

se você não conhece a função, pode ser feito de uma maneira diferente. Nem sempre é fácil. Mas você pode encontrá-lo de alguma forma por sua assinatura. Se este for o seu caso, informe-nos.


-1

Transmitir para o tipo real é fácil:

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

8
Isso é ilógico. Na verdade, você não conhece o tipo real. Como você deve fazer isso?
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 );
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.