Ответ 1
Это то, о чем вы думаете?
object result = Convert.ChangeType("4", Type.GetType("System.Int32"));
У меня есть следующее в С#:
string typename = "System.Int32";
string value = "4";
необходимо выполнить две строки для создания объекта указанного типа с указанным значением...
результат должен быть:
object o = CreateUnknownType(typename, value);
...
Int32 test = (Int32)o;
Это то, о чем вы думаете?
object result = Convert.ChangeType("4", Type.GetType("System.Int32"));
Как указано, это слишком широкое и не может быть разрешено в целом.
Вот несколько вариантов:
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"
), показывает, насколько абсурдной является общая проблема. Есть некоторые конструкции/преобразования, которые просто невозможно сделать.
Возможно, вам захочется переосмыслить проблему, которую вы пытаетесь решить, чтобы избежать этого болота.
Создание экземпляра типа, который вы знаете по имени (и который должен иметь конструктор по умолчанию):
string typeName = "System.Int32";
Type type = Type.GetType(type);
object o = Activator.CreateInstance(type);
Анализ значения из строки, очевидно, будет работать только для ограниченного набора типов. Вы могли
Convert.ChangeType
, как предложено
от PhilipWDictionary<Type,Func<string,object>>
который отображает известные типы в известный синтаксический анализ
Функцииили используйте отражение, чтобы вызвать Метод parse (string) для типа, предполагая, что есть один:
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);
Ваша логика кажется немного испорченной здесь. Очевидно, что если вы прямо накладываете объект на более поздний период на фактический тип, то вы должны знать тип, с которого нужно начинать.
Если есть что-то еще, что отсутствует в этом вопросе, пожалуйста, уточните, и, возможно, есть более подходящий ответ, чем просто: "Это не имеет большого смысла".
Возможно, у вас есть набор разных типов, все из которых реализуют известный интерфейс?
Например, если у вас есть несколько разных пользовательских элементов управления и вы хотите загрузить один из них в контейнер, каждый может реализовать IMyWobblyControl (известный интерфейс), но вы, возможно, не знаете до тех пор, пока не будет загружено какое-либо из них, возможно, из чтения строк из какого-либо файла конфигурации.
В этом случае вам нужно будет использовать отражение, чтобы загрузить фактический тип из чего-то типа полного имени сборки, а затем применить его к известному типу, чтобы использовать его.
Конечно, вам нужно убедиться, что ваш код обрабатывает недействительные листы, сборку не найден и любые другие исключения, которые могут возникнуть через что-то столь же шаткий, как это...
Это похоже на работу для Int32.Parse(string). Но, чтобы согласиться с другими, кажется, что это "уникально", и, вероятно, следует подумать о перчатках.
После использования:
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);
}
}
Надеюсь, что это поможет.
Здесь приведен конкретный пример проблемы с Azure SQL Federations..., которая разбивает данные на отдельные db в соответствии с диапазоном клавиш.
Ключевыми типами диапазонов являются:
SQL/.Net Тип SQL/ CLR.Net
INT/SqlInt32/Int32, Nullable
BIGINT/SqlInt64/Int64, Nullable
UNIQUEIDENTIFIER/SqlGuid/Guid, Nullable
VARBINARY (n), max n 900/SqlBytes, SqlBinary/Byte []
В идеале, параметр функции С# может принимать либо .NET тип SQL, либо тип CLR.Net, но только для одной категории типов.
Может ли тип объекта "объект" быть способным? И есть ли способ определить тип и преобразовать его соответственно?
Концепция выглядит примерно так:
public void fn (объект obj, string 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, поэтому требуется проверка его на стороне приложения.