C# 我如何将 Activator.CreateInstance 与字符串一起使用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2092530/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do i use Activator.CreateInstance with strings?
提问by
In my reflection code i hit a problem with my generic section of code. Specifically when i use a string.
在我的反射代码中,我的通用代码部分遇到了问题。特别是当我使用字符串时。
var oVal = (object)"Test";
var oType = oVal.GetType();
var sz = Activator.CreateInstance(oType, oVal);
Exception
例外
An unhandled exception of type 'System.MissingMethodException' occurred in mscorlib.dll
Additional information: Constructor on type 'System.String' not found.
I tried this for testing purposes and it occurs in this single liner too
我为了测试目的尝试了这个,它也发生在这个单衬里
var sz = Activator.CreateInstance("".GetType(), "Test");
originally i wrote
原来我写的
var sz = Activator.CreateInstance("".GetType());
but i get this error
但我收到这个错误
Additional information: No parameterless constructor defined for this object.
How do i create a string using reflection?
如何使用反射创建字符串?
采纳答案by Hans Passant
Keep in mind that the string class is immutable. It cannot be changed after it is created. That explains why it doesn't have a parameterless constructor, it could never generate a useful string object other than an empty string. That's already available in the C# language, it is "".
请记住,字符串类是不可变的。创建后无法更改。这就解释了为什么它没有无参数构造函数,它永远不会生成一个有用的字符串对象,而不是一个空字符串。这在 C# 语言中已经可用,它是“”。
Same reasoning applies for a string(String) constructor. There is no point in duplicating a string, the string you'd pass to the constructor is already a perfectly good instance of the string.
同样的推理适用于 string(String) 构造函数。复制字符串没有意义,您传递给构造函数的字符串已经是字符串的完美实例。
So fix your problem by testing for the string case:
因此,通过测试字符串大小写来解决您的问题:
var oType = oVal.GetType();
if (oType == typeof(string)) return oVal as string;
else return Activator.CreateInstance(oType, oVal);
回答by Guillaume
You are trying to do this :
您正在尝试这样做:
var sz = new string();
Try to compile it, you will understand your error.
试着编译它,你会明白你的错误。
You may try :
你可以试试:
var sz = Activator.CreateInstance(typeof(string), new object[] {"value".ToCharArray()});
But it looks useless, you should directly use value...
但是看起来没用,你应该直接使用价值......
回答by Jon Skeet
It looks like you're trying to call a constructor which just takes a string - and there isn't such a constructor. If you've already gota string, why are you trying to create a new one? (When you didn't provide any further arguments, you were trying to call a parameterless constructor - which again, doesn't exist.)
看起来您正在尝试调用一个只接受字符串的构造函数 - 并且没有这样的构造函数。如果你已经有了一个字符串,你为什么要尝试创建一个新的字符串?(当你没有提供任何进一步的参数时,你试图调用一个无参数的构造函数 - 这又是不存在的。)
Note that typeof(string)
is a simpler way to get a reference to the string type.
请注意,这typeof(string)
是获取字符串类型引用的更简单方法。
Could you give us more information about the bigger picture of what you're trying to do?
你能告诉我们更多关于你正在尝试做的事情的大局的信息吗?
回答by Tarydon
String actually has no constructor that takes a string as input. There is a constructor that takes a char array so this should work:
String 实际上没有将字符串作为输入的构造函数。有一个构造函数接受一个字符数组,所以这应该可以工作:
var sz = Activator.CreateInstance ("".GetType (), "Test".ToCharArray ());
回答by Hans Passant
This is what I use in my projects. As far as needing to create an instantiation of a type of object and not knowing at design time, is rather normal for me. Perhaps you are cycling through object properties and you want to instantiate all of them dynamically. I have many times needed to create then assign values to non instantiated POCO objects... with the below code you can use a string value stored in the DB to instantiate an object as well or instantiate an object stored in a library that is referencing your library - so you can bypass circular reference errors as well... Hope it helps.
这是我在我的项目中使用的。至于需要创建一个对象类型的实例并且在设计时不知道,对我来说是很正常的。也许您正在循环使用对象属性,并且想要动态地实例化所有这些属性。我有很多次需要创建然后将值分配给非实例化的 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);
}