Как привести объект к типу, описанному классом Type? - PullRequest
27 голосов
/ 30 июля 2009

У меня есть объект:

ExampleClass ex = new ExampleClass();

И

Type TargetType

Я хотел бы привести ex к типу, описанному TargetType, следующим образом:

Object o = (TargetType) ex;

Но когда я делаю это, я получаю:

Имя типа или пространства имен 't' может не найден

Так как это сделать? Я что-то упустил здесь?

Обновление:

Я бы хотел получить что-то вроде этого:

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

private otherClass;

И так как у меня будет много таких свойств, я хотел бы сделать это:

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

private SomeOtherTypeClass otherClass;

Контекст:

Обычно в моем контексте в моем классе мне нужно создать много свойств. И в каждом сменить кастинг на тип недвижимости. Это не имеет смысла для меня (в моем контексте), потому что я знаю, что такое возвращаемый тип, и я хотел бы написать какой-то код, который будет выполнять приведение для меня. Может быть, это случай дженериков, я пока не знаю.

Как будто я могу заверить в этом свойстве, что я получаю правильный объект в нужном типе и на 100% могу привести его к типу свойства.

Все, что мне нужно сделать, чтобы мне не нужно было указывать в каждом свойстве, что оно должно «приводить значение к CustomClass», я хотел бы сделать что-то вроде «приведения значения к тому же классу, что и это свойство. ».

Например:

class MYBaseClass
{
   protected List<Object> MyInternalObjects;
}

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

И хорошо - я могу сделать много свойств, как показано выше, - но есть 2 проблемы:

1) Мне нужно указать имя объекта в MyInternalObjects, но оно совпадает с именем свойства. Это я решил с помощью System.Reflection.MethodBase.GetCurrentMethod (). Name.

2) В каждом свойстве мне нужно привести объект из MyInternalObjects к разным типам. В MyVeryOwnSpecialObject например - в SpecialClass. Это всегда тот же класс, что и у свойства.

Вот почему я хотел бы сделать что-то вроде этого:

class MYBaseClass
{
   protected List<Object> MyInternalObjects;
}

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

А теперь касается: хорошо, зачем? Потому что в дальнейшем в моем приложении будут все преимущества безопасных типов и т. Д. (Intellisense).

Второй: а теперь вы потеряете безопасность типов в этом месте? Нет. Потому что я очень уверен, что у меня есть объект моего типа в списке.

Ответы [ 5 ]

11 голосов
/ 30 июля 2009
Object o = (TargetType) ex;

Этот код бесполезен. У вас может быть тип справа, но это все еще только объект с левой стороны. Вы не можете использовать функциональность, специфичную для TargetType, как это.


Вот как вы можете вызвать метод неизвестного объекта данного типа:

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

С этим классом UnknownType:

class UnknownType
{
    public void SayHello()
    {
        Console.WriteLine("Hello world.");
    }
}
3 голосов
/ 30 июля 2009

Обычно желание сделать это указывает на недоразумение. Тем не менее, существуют очень легитимные причины для этого. Это зависит от того, будет ли это эталонное преобразование против распаковки или пользовательского преобразования.

Если это эталонное преобразование, это означает, что фактическое значение (эталон) останется без изменений. Все, что делает приведение в действие, выполняет проверку, а затем копирует значение. Это не имеет никакого реального применения - вы можете выполнить проверку, используя вместо этого Type.IsAssignableFrom, и просто использовать неявное приведение к object, если вы хотите его в переменной типа object.

Основной целью приведения является предоставление компилятору дополнительной информации. Теперь, если вы знаете только тип во время выполнения , это явно не поможет компилятору.

Что вы планируете делать с o после того, как вы выполнили приведение? Если вы можете это объяснить, мы можем попытаться объяснить, как добиться желаемого эффекта.

Если вы действительно хотите, чтобы определяемое пользователем преобразование или преобразование без распаковки происходило, это может быть другим вопросом - но я подозреваю , что это не так.

РЕДАКТИРОВАТЬ: После просмотра вашего обновления ваша собственность только что объявила о возвращении CustomClass, поэтому все, что вам нужно, это:

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

Я подозреваю, что вы до сих пор не предоставили нам всю необходимую нам информацию. Это определенно , как будет определено ваше свойство, с CustomClass определенного типа? Почему вы пытались выполнить приведение динамически, когда вы знаете тип свойства?

РЕДАКТИРОВАТЬ: Похоже, вы просто пытаетесь сохранить некоторые печатать - чтобы было проще вырезать и вставлять. Не. Вы знаете тип во время компиляции, потому что вы знаете тип свойства во время компиляции (он указан в коде всего несколькими строками выше). Используйте этот тип напрямую. Точно так же не пытайтесь получить имя текущего метода, чтобы определить ключ для использования. Просто введите имя напрямую. Опять же, вы знаете это во время компиляции, так зачем быть динамичным? Я весь из-за лени, когда это имеет смысл, но в данном случае это просто не так.

1 голос
/ 22 сентября 2013

Я не совсем уверен, что вы пытаетесь сделать, но у меня сложилось впечатление, что вы хотели бы иметь один экземпляр какого-либо объекта, который может "вести себя как" множество различных типов объектов, и вы хотите иметь геттеры, которые позволят вам очень легко просматривать один и тот же объект различными способами. В этом случае я бы предложил создать один метод получения (а не свойство), например:

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

Тогда вы бы назвали это так:

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

Обратите внимание на две вещи: это определенно небезопасно, так как вы можете передать любой тип для T, включая типы, для которых приведение не удастся. Вы можете немного ограничить это, например так:

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

Что приведет к ошибке компиляции, если вы попытаетесь использовать тип, несовместимый с SomeBaseType, но я не уверен, что он полностью устойчив. Но, надеюсь, это даст вам большую часть пути.

Это то, что вы имели в виду?

1 голос
/ 14 августа 2009

Сейчас это кажется невозможным, но скоро будет доступна новая функция в .NET 4.0 под названием «динамическая»:

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

0 голосов
/ 30 июля 2009
if (ex is ExampleClass) 
{
  ExampleClass myObject = (ExampleClass)ex;
}

Это сделало бы это, но я думаю, вопрос в том, чего ты пытаешься достичь и почему? Я часто нахожу, что если что-то кажется действительно, действительно трудным, то, вероятно, я делаю это неправильно.

...