C# 如何将Activator.CreateInstance与字符串一起使用?

C# 如何将Activator.CreateInstance与字符串一起使用?,c#,.net,reflection,activator,C#,.net,Reflection,Activator,在我的反射代码中,我的泛型代码部分遇到了一个问题。特别是当我使用字符串时 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 info

在我的反射代码中,我的泛型代码部分遇到了一个问题。特别是当我使用字符串时

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.

如何使用反射创建字符串?

您正在尝试这样做:

var sz = new string();
试着编译它,你就会明白你的错误

你可以尝试:

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

但是它看起来没用,你应该直接使用value…

看起来你试图调用一个只接受一个字符串的构造函数,而没有这样的构造函数。如果您已经有一个字符串,为什么要创建一个新的呢?(当您没有提供任何进一步的参数时,您正试图调用一个无参数构造函数,而该构造函数同样不存在。)

请注意,
typeof(string)
是获取字符串类型引用的更简单方法


你能给我们提供更多关于你要做的事情的信息吗?

String实际上没有以字符串作为输入的构造函数。有一个构造函数接受一个char数组,因此应该可以:

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

请记住,string类是不可变的。它在创建后无法更改。这就解释了为什么它没有无参数构造函数,除了空字符串,它永远不会生成有用的字符串对象。这在C语言中已经可用,它是“”

同样的推理也适用于字符串(string)构造函数。复制字符串没有意义,传递给构造函数的字符串已经是该字符串的完美实例

因此,通过测试字符串大小写来解决您的问题:

var oType = oVal.GetType();
if (oType == typeof(string)) return oVal as string;
else return Activator.CreateInstance(oType, oVal);

这是我在项目中使用的。至于需要创建对象类型的实例化而在设计时不知道,这对我来说是很正常的。也许您正在循环浏览对象属性,并且希望动态实例化所有这些属性。我需要多次创建并将值分配给非实例化的POCO对象。。。使用下面的代码,您可以使用存储在DB中的字符串值来实例化对象,或者实例化存储在引用您的库的库中的对象-这样您也可以绕过循环引用错误。。。希望能有帮助

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);
}
使用系统;
使用System.Collections.Generic;
利用制度全球化;
运用系统反思;
/// 
///实例化一个对象。工厂必须通过PropertyType.AssemblyQualifiedName才能运行
///返回实例化的对象
/// 
/// 
/// 
公共静态对象创建(字符串类型AssemblyQualifiedName)
{
//解析类型
类型targetType=ResolveType(类型AssemblyQualifiedName);
if(targetType==null)
抛出新ArgumentException(“无法解析对象类型:“+typeAssemblyQualifiedName”);
返回创建(targetType);
}
/// 
///按T类型创建
/// 
/// 
/// 
publicstatict-Create()
{
类型targetType=类型(T);
返回(T)创建(targetType);
}
/// 
///一般对象创建
/// 
/// 
/// 
公共静态对象创建(类型targetType)
{
//首先进行字符串测试-它没有无参数构造函数
if(Type.GetTypeCode(targetType)==TypeCode.String)
返回字符串。空;
//获取默认构造函数并实例化
类型[]类型=新类型[0];
ConstructorInfo=targetType.GetConstructor(类型);
对象targetObject=null;
if(info==null)//必须没有找到构造函数
if(targetType.BaseType.UnderlyingSystemType.FullName.Contains(“枚举”))
targetObject=Activator.CreateInstance(targetType);
其他的
抛出新ArgumentException(“无法实例化类型:“+targetType.AssemblyQualifiedName+”-未找到构造函数”);
其他的
targetObject=info.Invoke(null);
if(targetObject==null)
抛出新ArgumentException(“无法实例化类型:“+targetType.AssemblyQualifiedName+”-未知错误”);
返回目标对象;
}
/// 
///加载对象的部件。工厂必须通过PropertyType.AssemblyQualifiedName才能运行
///返回对象类型。
/// 
/// 
/// 
公共静态类型ResolveType(字符串类型AssemblyQualifiedName)
{
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);
//获取包含处理程序的程序集
Assembly=null;
尝试
{
assembly=assembly.Load(assemblyName);
}
抓住
{
尝试
{
assembly=assembly.LoadWithPartialName(assemblyName);//是的,这已过时,但只是一个备份调用
}
抓住
{
抛出新ArgumentException(“无法加载程序集”+assemblyName);
}
}
//找到处理程序
返回assembly.GetType(className,false,false);
}

实际上他正在尝试
var s=newstring(“Test”)
我说的是这一行:var sz=Activator.CreateInstance(“.GetType()”);我现在明白了。我不希望做if声明或任何特殊检查。看来我得走了。谢谢。有没有其他课程可以证明这个问题?或者,我可以解决一般问题(对于任意类型?)我通过反射和sqlitedatareader读取对象。我不知道椭圆是否是字符串,除非我写了一个我想避免的if语句。此外,我正在使用fieldtype,我可能正在创建一个接受字符串的对象。nobugz提到字符串是不可变的,所以我想我必须写一个if语句来检查fieldtype是否是字符串。与从字符串重建对象所涉及的其他黑客相比,我认为一个简单的“这已经是字符串了吗”检查可能是你最不担心的:)