2009-11-12 2 views
11

я получил следующее C#:Как создать экземпляр неизвестного типа во время выполнения?

string typename = "System.Int32"; 
string value = "4"; 

тезисах две строки должны быть приняты для создания объекта указанного типа с заданным значением ...

результат должен быть:

object o = CreateUnknownType(typename, value); 
... 
Int32 test = (Int32)o; 
+4

И ваш вопрос? Зачем пытаться создать неизвестное, если позже вы перейдете его к известному типу? – Lazarus

+6

Вопрос: Как сгенерировать экземпляр неизвестного типа во время выполнения? Неважно, почему или нет, я просто хочу знать, возможно ли его возможное – haze4real

+2

Это легко, да, это возможно. Возможно ли это? Возможно нет. Неразумно ли задавать какой-то контекст, когда ваш пример не имеет смысла? – Lazarus

ответ

20

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

object result = Convert.ChangeType("4", Type.GetType("System.Int32")); 
+0

Да, вот и все, спасибо – haze4real

1

Ваша логика здесь немного испорчена. Очевидно, что если вы непосредственно накладываете объект на более поздний период на фактический тип, то вы должны знать тип для начала.

Если есть что-то еще, что отсутствует в этом вопросе, пожалуйста, уточните, и, возможно, есть более подходящий ответ, чем просто: «Это не имеет большого смысла».

0

Это похоже на работу для Int32.Parse (string). Но, чтобы согласиться с другими, кажется, что это «уникально», и, вероятно, следует подумать о перчатках.

15

Как уже говорилось, это слишком широкое и не может быть разрешено в целом.

Вот некоторые варианты:

Type type = Type.GetType(typename); 
object o = Activator.CreateInstance(type); 

Это создаст экземпляр типа, который typename описывает. Он вызывает конструктор без параметров. (Даунсайд: Не все объекты имеют конструктор без параметров Далее, это установить состояние объекта с помощью value.).

Type type = Type.GetType(typename); 
object o = Activator.CreateInstance(type, new[] { value }); 

Это создаст экземпляр типа, который typename описывает. Он вызывает конструктор этого типа, который принимает один параметр типа string. (Даунсайд: Не все объекты имеют такой конструктор, например, Int32 не имеет такой конструктор, так что вы будете испытывать исключение во время выполнения.).

Type type = Type.GetType(typename); 
object o = Convert.ChangeType(value, type); 

Это делается попытка преобразовать строку value к экземпляру требуемый тип. Это может привести к InvalidCastException. Например, Convert.ChangeType("4", typeof(FileStream)), очевидно, не удастся, как и должно быть.

Фактически этот последний пример (создать экземпляр типа FileStream с его начальным состоянием, определяемым строкой "4") показывает, насколько абсурдной является общая проблема. Есть некоторые конструкции/преобразования, которые просто невозможно сделать.

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

+0

Возможно, я должен, спасибо, что объяснил возможности ... – haze4real

3

Создание экземпляра типа вы знаете, по имени (и который должен иметь конструктор по умолчанию):

string typeName = "System.Int32"; 
    Type type = Type.GetType(type); 
    object o = Activator.CreateInstance(type); 

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

  • использование Convert.ChangeType как предложено по PhilipW
  • или, возможно, создать Dictionary<Type,Func<string,object>> , переводящий известных типов до известной разборе функции
  • или использовать отражение для вызова Разбор метод (строка) по типу, при условии, что существует один:

    string valueText = "4"; 
        MethodInfo parseMethod = type.GetMethod("Parse"); 
        object value = parseMethod.Invoke(null, new object[] { valueText }); 
    
  • или, возможно, вы можете использовать инфраструктуру , предоставляемую компонентом модели .NET . Вы можете принести преобразователь типа компонента и использовать это нравится:

    TypeConverter converter = TypeDescriptor.GetConverter(type); 
        object value = converter.ConvertFromString(valueText); 
    
0

После использования:

Type type = Type.GetType(typename); 

Попробуйте этот метод расширения:

public static class ReflectionExtensions 
{ 
    public static T CreateInstance<T>(this Type source, params object[] objects) 
     where T : class 
    {    
     var cons = source.GetConstructor(objects.Select(x => x.GetType()).ToArray()); 
     return cons == null ? null : (T)cons.Invoke(objects); 
    } 
} 

Надежда это помогает.

1

Возможно, у вас есть набор различных типов, все из которых реализуют известный интерфейс?

Например, если у вас есть несколько различных элементов управления пользователя и вы хотите загрузить один из них в контейнер, каждый из них может реализовать IMyWobblyControl (известный интерфейс), но вы, возможно, не знаете до тех пор, пока не будет загружено какое-либо из них, строки из какого-либо файла конфигурации.

В этом случае вам нужно использовать отражение, чтобы загрузить фактический тип из чего-то типа полного имени сборки, а затем применить его к известному типу, чтобы использовать его.

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

0

Вот конкретный пример проблемы с Azure SQL Federations ..., которая разбивает данные на отдельные db в соответствии с диапазоном ключей.

Основные типы диапазона являются:

SQL/.Net типа SQL/CLR .Net

INT/SqlInt32/Int32, Nullable

BIGINT/SqlInt64/Int64 , Nullable

UNIQUEIDENTIFIER/SqlGuid/Guid, Nullable

VARBINARY (п), не более п 900/SqlBytes, SqlBinary/Byte []

В идеале, # функция парам C может принимать либо .Net типа SQL или типа CLR .Net, но завещать только одну категорию типа Это хорошо.

Может ли быть тип объекта «объект»? И есть ли способ определить тип и преобразовать его соответственно?

Концепция что-то вроде:

общественного ничтожной Fn (объект OBJ, струнный fedName, струнный DISTNAME, BOOL filteringOn)

{

... выяснить, что OBJ типа является обеспечение это один из приемлемых типов ...

string key = obj.toString();

return string.Format ("USE FEDERATION {0} ({1} = '{2}') WITH RESET, FILTERING = {3}", fedName, distName, key, (filteringOn? "ON": " OFF "));

}

Хотя значение паров приводятся к строке, то он будет переделка/проверено на стороне сервера, так SQL проверки его на стороне приложения желательно.

Смежные вопросы