2012-09-02 22 views
71

Se ho:Come trasmettere Oggetto al suo tipo effettivo?

void MyMethod(Object obj) { ... } 

Come posso lanciare obj a ciò che il suo tipo effettivo è?

+2

è il tipo noto al momento della compilazione? – psubsee2003

+1

E cosa ti aspetti di ottenere da questo? Per favore, dicci cosa stai cercando di ottenere, piuttosto che come pensi di ottenerlo. –

+0

@JonSkeet: voglio essere in grado di chiamare una funzione dall'oggetto. Attualmente 'obj.MyFunction();' non compila, anche se so che l'oggetto reale ha quella funzione. –

risposta

117

Se si conosce il tipo effettivo, poi basta:

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

Se non si conosce il tipo effettivo, quindi: non proprio, no. Si dovrebbe utilizzare invece uno dei:

  • riflessione
  • implementare un'interfaccia ben nota
  • dinamica

Ad esempio:

// 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(); 
+0

Qual è la sintassi equivalente in Swift? – Rao

+1

Nevermind, ha trovato la funzione 'as' per typecasting e' type (of: ClassName) 'per verificare il tipo di istanza. – Rao

0

Casting di tipo effettivo è facile:

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

è molto divertente ... – Steve

+1

Questo è illogico. In realtà non conosci il tipo attuale. Come dovresti farlo? –

28

Non credo puoi (non senza riflettere), dovresti anche fornire un tipo alla tua funzione:

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

UPD:

Questo può funzionare per voi:

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

Questa è davvero una risposta inutile, non meritevole di voti positivi. La riflessione di un oggetto di tipo oggetto non produrrà il "tipo effettivo" dell'oggetto, come richiesto da OP. Inoltre, la logica MyMethod è difettosa perché obj può essere di tipo A e può anche essere di tipo B. La logica non fornisce il "tipo effettivo" (come richiesto dall'OP) - fornisce un tipo compatibile e non necessariamente il tipo desiderato a quello – Jazimov

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

Se il metodo MyFunction() è definito solo in una classe (e le sue discendenti), provate

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

Se si dispone di un gran numero di classi non correlate definire la funzione che si desidera chiamare, si dovrebbe definire un'interfaccia e fare le vostre classi definiscono tale interfaccia:

interface IMyInterface 
{ 
    void MyFunction(); 
} 

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

Fusioni al suo tipo reale se ora il tipo per esempio è orientato dalla classe di nome abc. È possibile chiamare la funzione in questo modo:

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

se non si conosce la funzione può essere fatto in modo diverso. Non è sempre facile. Ma puoi trovarlo in qualche modo dalla sua firma. Se questo è il tuo caso, dovresti comunicarcelo.

0

Nel mio caso AutoMapper funziona bene.

automapper può mappare da/per gli oggetti dinamici senza alcuna configurazione esplicita:

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

Allo stesso modo è possibile mappare direttamente dalla dizionari di oggetti, automapper schiererà i tasti con i nomi di proprietà.

maggiori informazioni https://github.com/AutoMapper/AutoMapper/wiki/Dynamic-and-ExpandoObject-Mapping

Problemi correlati