Comment convertir un objet dans son type réel?

121

Si j'ai:

void MyMethod(Object obj) {   ...   }

Comment puis-je convertir objce type de contenu?

Paul Lassiter
la source
2
Le type est-il connu au moment de la compilation?
psubsee2003
1
Et qu'espérez-vous en faire? Veuillez nous dire ce que vous essayez d'atteindre, plutôt que comment vous comptez y parvenir.
Jon Skeet
@JonSkeet: Je veux pouvoir appeler une fonction à partir de l'objet. Actuellement, obj.MyFunction();ne compile pas, même si je sais que l'objet réel a cette fonction.
Paul Lassiter le
@ psubsee2003: non, ce n'est pas le cas, car c'est une référence d'objet passée via l'interopérabilité.
Paul Lassiter
3
@PaulLassiter: Si vous ne connaissez pas le type, qu'est-ce qui déclare la MyFunctionméthode?
Jon Skeet

Réponses:

194

Si vous connaissez le type réel, alors juste:

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

Si vous ne connaissez pas le type réel, alors: pas vraiment, non. Vous devrez à la place utiliser l'un des éléments suivants:

  • réflexion
  • implémenter une interface bien connue
  • dynamique

Par exemple:

// 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();
Marc Gravell
la source
1
Quelle est la syntaxe équivalente dans Swift?
Nagendra Rao
1
Nevermind, trouvé aspour le typage et type(of: ClassName)fonction pour vérifier le type d'instance.
Nagendra Rao
43

Je ne pense pas que vous puissiez (non sans réflexion), vous devriez également fournir un type à votre fonction:

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

UPD :

Cela peut fonctionner pour vous:

void MyMethod(Object obj)
{
    if (obj is A)
    {
        A a = obj as A;
        ...
    } 
    else if (obj is B)
    {
        B b = obj as B;
        ...
    }
}
Maksim Vi.
la source
4
C'est vraiment une réponse inutile, qui ne mérite pas de votes positifs. La réflexion d'un objet de type objet ne donnera pas le "type réel" de l'objet, comme demandé par OP. De plus, votre logique MyMethod est imparfaite car obj peut être de type A et il peut également être de type B. Votre logique ne fournit pas le "type réel" (comme OP demandé) - il fournit un type compatible, et pas nécessairement le type souhaité à cela.
Jazimov
utilisez obj.GetType (). Cela retournera certainement son type réel.
JSON
3

Que diriez-vous de JsonConvert.DeserializeObject (object.ToString ());

albin
la source
Ce n’est pas une réponse satisfaisante. La question d'OP n'a rien à voir avec Json ou la sérialisation.
@ user12637955 c'est en fait une réponse fonctionnelle, mais elle est plus complexe, en raison de la boxe et du déballage, c'est-à-dire object -> ToString () -> to concret type. Pour être plus précis, cela devrait ressembler à ceci:var myType = JsonConvert.DeserializeObject<MyType>(object.ToString());
Coke
1

Dans mon cas, AutoMapper fonctionne bien.

AutoMapper peut mapper vers / depuis des objets dynamiques sans aucune configuration explicite:

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 même, vous pouvez mapper directement des dictionnaires aux objets, AutoMapper alignera les clés avec les noms de propriété.

plus d'infos https://github.com/AutoMapper/AutoMapper/wiki/Dynamic-and-ExpandoObject-Mapping

Soren
la source
1

Cette méthode n'est peut-être pas la plus efficace, mais elle est simple et fait le travail.

Il effectue deux opérations: d'abord il appelle .ToString () qui est fondamentalement une sérialisation, puis la désérialisation à l'aide de Newtonsoft nuget (que vous devez installer).

public T Format<T>(Object obj) =>
    JsonConvert.DeserializeObject<T>(obj.ToString());
bombek
la source
Vous devez décrire brièvement votre réponse pour les futurs lecteurs.
Suraj Kumar le
0

Si votre MyFunction()méthode est définie uniquement dans une classe (et ses descendants), essayez

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

Si vous avez un grand nombre de classes non liées définissant la fonction que vous souhaitez appeler, vous devez définir une interface et faire en sorte que vos classes définissent cette interface:

interface IMyInterface
{
    void MyFunction();
}

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

Transformez-le en son type réel si vous maintenant le type, par exemple, il est orienté à partir de la classe nommée abc. Vous pouvez appeler votre fonction de cette manière:

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

si vous ne connaissez pas la fonction, cela peut être fait d'une manière différente. Pas toujours facile. Mais vous pouvez le trouver d'une certaine manière par sa signature. Si tel est votre cas, vous devez nous le faire savoir.

Masoud
la source
-1

La diffusion au type réel est facile:

void MyMethod(Object obj) {
    ActualType actualyType = (ActualType)obj;
}
user1610694
la source
8
C'est illogique. En fait, vous ne connaissez pas le type réel. Comment es-tu censé faire ça?
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 );
}
Hassan Boutougha
la source