繁体   English   中英

我如何使用Activator.CreateInstance与字符串?

[英]How do i use Activator.CreateInstance with strings?

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

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.

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

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

相同的推理适用于string(String)构造函数。 重复一个字符串是没有意义的,你传递给构造函数的字符串已经是一个非常好的字符串实例。

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

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

你正试图这样做:

var sz = new string();

尝试编译它,你就会明白你的错误。

你可以尝试:

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

但它看起来没用,你应该直接使用价值......

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

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

您能否向我们提供更多有关您想要做的事情的更多信息?

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

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

这就是我在项目中使用的内容。 至于需要创建一种对象类型的实例化并且在设计时不知道,对我来说是相当正常的。 也许您正在循环访问对象属性,并且您希望动态地实例化所有这些属性。 我有很多次需要创建然后为非实例化的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);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM