web-dev-qa-db-fra.com

Comment convertir un objet en un type décrit par la classe Type?

J'ai un objet:

ExampleClass ex = new ExampleClass();

Et:

Type TargetType

Je voudrais convertir ex au type décrit par TargetType comme ceci:

Object o = (TargetType) ex;

Mais quand je fais cela, je reçois:

Le type ou le nom de l'espace de noms 't' pourrait ne pas être trouvé

Alors comment le faites vous? Est-ce que je manque quelque chose d'obieux ici?

Mettre à jour:

Je voudrais obtenir quelque chose comme ça:

public CustomClass MyClassOuter
{
   get
   {
        return (CustomClass) otherClass;
   }
}

private otherClass;

Et parce que j'aurai beaucoup de propriétés comme celle-ci, j'aimerais faire ceci:

public CustomClass MyClassOuter
{
   get
   {
        return (GetThisPropertyType()) otherClass;
   }
}

private SomeOtherTypeClass otherClass;

Le contexte:

Normalement, dans mon contexte de classe, j'ai besoin de créer de nombreuses propriétés. Et dans chacun remplacer le moulage au type de propriété. Cela ne semble pas avoir de sens pour moi (dans mon contexte) car je sais quel type de retour est et je voudrais écrire une sorte de code qui fera le casting pour moi. Peut-être que c'est le cas des génériques, je ne sais pas encore. 

C'est comme si je pouvais assurer dans cette propriété que j'obtiens le bon objet et le bon type et que je suis à 100% capable de le convertir en type. 

Tout ce que j'ai besoin de faire pour ne pas avoir à spécifier dans chaque propriété qu'il doit "attribuer une valeur à CustomClass", j'aimerais faire quelque chose comme "attribuer une valeur à la même classe que cette propriété est".

Par exemple:

class MYBaseClass
{
   protected List<Object> MyInternalObjects;
}

class MyClass
{
   public SpecialClass MyVeryOwnSpecialObject
   {
      get
      {
           return (SpecialClass) MyInteralObjects["MyVeryOwnSpecialObject"];
      }
   }
}

Et ok - je peux faire beaucoup de propriétés comme celle-ci ci-dessus - mais il y a 2 problèmes: 

1) Je dois spécifier le nom de l'objet sur MyInternalObjects, mais c'est le même nom de propriété. J'ai résolu ce problème avec System.Reflection.MethodBase.GetCurrentMethod (). Name.

2) Dans chaque propriété, j'ai besoin de convertir l'objet de MyInternalObjects en différents types. Dans MyVeryOwnSpecialObject, par exemple, vers SpecialClass. C'est toujours la même classe que la propriété.

C'est pourquoi j'aimerais faire quelque chose comme ceci:

class MYBaseClass
{
   protected List<Object> MyInternalObjects;
}

class MyClass
{
   public SpecialClass MyVeryOwnSpecialObject
   {
      get
      {
           return (GetPropertyType()) MyInteralObjects[System.Reflection.MethodBase.GetCurrentMethod().Name];
      }
   }
}

Et maintenant concerne: Ok, pour quoi faire? Parce que plus loin dans ma candidature, j'aurai tous les avantages des types sécurisés, etc. (intellisense).

Deuxième: mais maintenant vous allez perdre la sécurité de type dans cet endroit? Non, parce que je suis très sûr d'avoir un objet de mon type sur une liste.

27
Tomasz Smykowski

Maintenant, cela semble être impossible, mais sera bientôt disponible avec une nouvelle fonctionnalité dans .NET 4.0 appelée "dynamique":

http://www.codeguru.com/vb/vbnet30/article.php/c15645__4/

1
Tomasz Smykowski
Object o = (TargetType) ex;

Ce code est inutile. Vous pouvez avoir un type à droite mais il ne reste qu'un objet à gauche. Vous ne pouvez pas utiliser une fonctionnalité spécifique à TargetType comme ceci.


Voici comment vous pouvez invoquer une méthode d'un objet inconnu d'un type donné:

object myObject = new UnknownType();
Type t = typeof(UnknownType); // myObject.GetType() would also work
MethodInfo sayHelloMethod = t.GetMethod("SayHello");
sayHelloMethod.Invoke(myObject, null);

Avec cette classe UnknownType:

class UnknownType
{
    public void SayHello()
    {
        Console.WriteLine("Hello world.");
    }
}
11
weiqure

Habituellement, le désir de le faire indique un malentendu. Cependant, il y a sont très occasionnellement des raisons légitimes de le faire. Cela dépend si oui ou non il s'agira d'une conversion de référence par rapport à une conversion unboxing ou définie par l'utilisateur.

S'il s'agit d'une conversion de référence, cela signifie que la valeur réelle (la référence) restera entièrement inchangée. Tout ce que le casting fait est d’effectuer une vérification puis de copier la valeur. Cela n'a aucune utilité réelle - vous pouvez effectuer la vérification en utilisant Type.IsAssignableFrom à la place et utilisez simplement la conversion implicite en object si vous le souhaitez dans une variable de type object.

L’intérêt principal de la conversion est de fournir au compilateur plus d’informations. Maintenant, si vous ne connaissez que le type à exécution heure, cela ne pourra clairement pas aider le compilateur.

Que comptez-vous faire avec o après avoir joué le casting? Si vous pouvez expliquer cela, nous pouvons essayer d’expliquer comment obtenir l’effet recherché.

Si vous voulez vraiment une conversion définie par l'utilisateur ou une conversion unboxing, cela pourrait être différent - mais je suspect ce n'est pas le cas.

EDIT: Après avoir vu votre mise à jour, votre propriété vient d’être déclarée comme retournant CustomClass, vous n'avez donc besoin que de:

public CustomClass MyClassOuter
{
   get
   {
        return (CustomClass) otherClass;
   }
}

Je suppose que vous ne nous avez toujours pas vraiment fourni toutes les informations dont nous avons besoin. Est-ce que c'est certainement comment votre propriété sera définie, avec CustomClass étant un type défini? Pourquoi avez-vous essayé d'effectuer le casting de manière dynamique lorsque vous connaissez le type de propriété?

EDIT: On dirait que vous essayez simplement d’enregistrer du texte en tapant - pour faciliter le copier-coller. Ne pas Vous connaissez le type au moment de la compilation, car vous connaissez le type de la propriété au moment de la compilation (il est spécifié dans le code à quelques lignes ci-dessus). Utilisez ce type directement. De même, n'essayez pas d'obtenir le nom de la méthode actuelle pour déterminer la clé à utiliser. Il suffit de mettre le nom directement. Encore une fois, vous le savez au moment de la compilation, alors pourquoi être dynamique? Je suis tout pour la paresse quand cela a du sens, mais dans ce cas, ça ne l'est tout simplement pas.

3
Jon Skeet

Je ne suis pas tout à fait sûr de ce que vous essayez de faire, mais j'ai l’impression que vous voudriez avoir une seule instance d’un objet qui puisse "agir comme" de nombreux types d’objets différents, et vous voulez d'avoir des getters qui vous permettront de voir cet objet de différentes manières très facilement. Dans ce cas, je suggèrerais de créer une méthode de lecture unique (pas une propriété), comme ceci:

public T Get<T>()
{
   return (T)myObject;
}

Alors tu l'appellerais comme ceci:

Foo foo = box.Get<Foo>();
Bar bar = box.Get<Bar>();
// etc...

Deux choses à noter: ceci n’est certainement pas digne de confiance, car vous pouvez passer n’importe quel type pour T, y compris les types pour lesquels la conversion échouera. Vous pouvez le contraindre un peu, comme ceci:

public T Get<T>() where T : SomeBaseType

Ce qui provoquera une erreur de compilation si vous essayez d'utiliser un type incompatible avec SomeBaseType, mais je ne suis pas sûr que ce soit tout à fait robuste. Mais j'espère que cela vous mènera presque jusqu'au bout.

Est-ce ce que vous aviez en tête?

1
gzak
if (ex is ExampleClass) 
{
  ExampleClass myObject = (ExampleClass)ex;
}

Cela le ferait, mais je suppose que la question est de savoir ce que vous essayez d’atteindre et pourquoi. Je trouve souvent que si quelque chose semble vraiment, vraiment difficile, alors je le fais probablement mal.

0
Lazarus