Как использовать Activator.CreateInstance со строками? - PullRequest
27 голосов
/ 19 января 2010

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

var oVal = (object)"Test";
var oType = oVal.GetType();
var sz = Activator.CreateInstance(oType, oVal);

Исключение

An unhandled exception of type 'System.MissingMethodException' occurred in mscorlib.dll

Additional information: Constructor on type 'System.String' not found.

Я пробовал это в целях тестирования, и это происходит в этом одном вкладыше тоже

var sz = Activator.CreateInstance("".GetType(), "Test");

Первоначально я написал

var sz = Activator.CreateInstance("".GetType());

но я получаю эту ошибку

Additional information: No parameterless constructor defined for this object.

Как мне создать строку, используя отражение?

Ответы [ 5 ]

41 голосов
/ 19 января 2010

Имейте в виду, что класс string является неизменным.Его нельзя изменить после его создания.Это объясняет, почему у него нет конструктора без параметров, он никогда не сможет создать полезный строковый объект, кроме пустой строки.Это уже доступно на языке C #, это "".

То же самое относится к строковому (String) конструктору.Нет смысла дублировать строку, строка, которую вы передадите в конструктор, уже является отличным экземпляром строки.

Так что исправьте свою проблему, протестировав регистр строки:

var oType = oVal.GetType();
if (oType == typeof(string)) return oVal as string;
else return Activator.CreateInstance(oType, oVal);
5 голосов
/ 19 января 2010

Вы пытаетесь сделать это:

var sz = new string();

Попробуйте скомпилировать, вы поймете свою ошибку.

Вы можете попробовать:

var sz = Activator.CreateInstance(typeof(string), new object[] {"value".ToCharArray()});

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

2 голосов
/ 30 июня 2015

Это то, что я использую в своих проектах.Что касается необходимости создания экземпляра типа объекта и незнания во время разработки, для меня это вполне нормально.Возможно, вы перебираете свойства объекта и хотите создать все из них динамически.Мне много раз приходилось создавать, а затем присваивать значения объектам POCO без создания экземпляра ... с помощью приведенного ниже кода вы можете использовать строковое значение, хранящееся в БД, для создания экземпляра объекта, а также для создания объекта, хранящегося в библиотеке, которая ссылается набиблиотека - так что вы также можете обойти ошибки круговой ссылки ... Надеюсь, это поможет.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;

/// <summary>
/// Instantiates an object. Must pass PropertyType.AssemblyQualifiedName for factory to operate
/// returns instantiated object
/// </summary>
/// <param name="typeName"></param>
/// <returns></returns>
public static object Create(string typeAssemblyQualifiedName)
{
  // resolve the type
  Type targetType = ResolveType(typeAssemblyQualifiedName);
  if (targetType == null)
    throw new ArgumentException("Unable to resolve object type: " + typeAssemblyQualifiedName);

  return Create(targetType);
}

/// <summary>
/// create by type of T
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T Create<T>()
{
  Type targetType = typeof(T);
  return (T)Create(targetType);
}

/// <summary>
/// general object creation
/// </summary>
/// <param name="targetType"></param>
/// <returns></returns>
public static object Create(Type targetType)
{
  //string test first - it has no parameterless constructor
  if (Type.GetTypeCode(targetType) == TypeCode.String)
    return string.Empty;

  // get the default constructor and instantiate
  Type[] types = new Type[0];
  ConstructorInfo info = targetType.GetConstructor(types);
  object targetObject = null;

  if (info == null) //must not have found the constructor
    if (targetType.BaseType.UnderlyingSystemType.FullName.Contains("Enum"))
      targetObject = Activator.CreateInstance(targetType);
    else
      throw new ArgumentException("Unable to instantiate type: " + targetType.AssemblyQualifiedName + " - Constructor not found");
  else
    targetObject = info.Invoke(null);

  if (targetObject == null)
    throw new ArgumentException("Unable to instantiate type: " + targetType.AssemblyQualifiedName + " - Unknown Error");
  return targetObject;
}

/// <summary>
/// Loads the assembly of an object. Must pass PropertyType.AssemblyQualifiedName for factory to operate
/// Returns the object type.
/// </summary>
/// <param name="typeString"></param>
/// <returns></returns>
public static Type ResolveType(string typeAssemblyQualifiedName)
{
  int commaIndex = typeAssemblyQualifiedName.IndexOf(",");
  string className = typeAssemblyQualifiedName.Substring(0, commaIndex).Trim();
  string assemblyName = typeAssemblyQualifiedName.Substring(commaIndex + 1).Trim();

  if (className.Contains("[]"))
    className.Remove(className.IndexOf("[]"), 2);

  // Get the assembly containing the handler
  Assembly assembly = null;
  try
  {
    assembly = Assembly.Load(assemblyName);
  }
  catch
  {
    try
    {
      assembly = Assembly.LoadWithPartialName(assemblyName);//yes yes this is obsolete but it is only a backup call
    }
    catch
    {
      throw new ArgumentException("Can't load assembly " + assemblyName);
    }
  }

  // Get the handler
  return assembly.GetType(className, false, false);
}
2 голосов
/ 19 января 2010

Строка на самом деле не имеет конструктора, который принимает строку в качестве входных данных. Существует конструктор, который принимает массив символов, поэтому он должен работать:

var sz = Activator.CreateInstance ("".GetType (), "Test".ToCharArray ());
2 голосов
/ 19 января 2010

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

Обратите внимание, что typeof(string) - это более простой способ получить ссылку настроковый тип.

Не могли бы вы дать нам больше информации о более широкой картине того, что вы пытаетесь сделать?

...