我在 C# 中有以下代码:
string typename = "System.Int32";
string value = "4";
这两个字符串应该被使用来生成一个指定类型和指定值的对象...结果应该是:
object o = CreateUnknownType(typename, value);
...
Int32 test = (Int32)o;
我在 C# 中有以下代码:
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
as suggested
by PhilipWDictionary<Type,Func<string,object>>
which maps known types to known parse
functionsor use reflection to invoke the Parse(string) method on the type, assuming there is one:
string valueText = "4";
MethodInfo parseMethod = type.GetMethod("Parse");
object value = parseMethod.Invoke(null, new object[] { valueText });
or maybe you can use the infrastructure provided by the .NET component model. You can fetch the type converter of a component and use it like this:
TypeConverter converter = TypeDescriptor.GetConverter(type);
object value = converter.ConvertFromString(valueText);
你的逻辑似乎有点错误。显然,如果你稍后直接将对象转换为它实际的类型,那么你必须一开始就知道这个类型。
如果这个问题还有其他缺失,请详细说明,也许有比“这没有多大意义”更合适的答案。
也许你有一组不同类型的对象,它们都实现了一个已知的接口?
例如,如果你有几个不同的用户控件,并且想要将其中一个加载到容器中,每个控件可能都实现了IMyWobblyControl(一个已知的接口),但是在运行时可能不知道要加载哪个控件,可能需要从某种配置文件中读取字符串。
在这种情况下,您需要使用反射从类似完整程序集名称的内容中加载实际类型,然后将其强制转换为已知类型以使用它。
当然,您需要确保您的代码处理无效的转换、找不到程序集和其他异常,因为这些问题很可能会出现在这种不稳定的情况下...
使用后:
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);
}
}
这似乎是 Int32.Parse(string) 的工作。但为了与其他人达成一致,似乎这是“独特”的,所以可能应该考虑手套。
这里是一个关于Azure SQL Federations的问题的具体示例...它将数据根据密钥范围拆分为不同的数据库。
密钥范围类型如下:
SQL / .Net SQL type / CLR .Net
INT / SqlInt32 / Int32,Nullable
BIGINT / SqlInt64 / Int64,Nullable
UNIQUEIDENTIFIER / SqlGuid / Guid,Nullable
VARBINARY(n),最大n 900 / SqlBytes、SqlBinary / Byte[]
理想情况下,C#函数参数可以采用.NET SQL类型或CLR .NET类型,但仅选择一种类型类别也可以。
使用“对象”类型参数是否是正确的方式?而且,有没有可行的方法来识别类型并相应地进行转换?
大致的概念如下:
public void fn(object obj, string fedName, string distName, bool filteringOn)
{
...找出 obj 的类型,确保它是可接受的类型之一...
string key = obj.toString();
return string.Format("使用 FEDERATION {0} ({1}='{2}') WITH RESET, FILTERING = {3}", fedName, distName, key, (filteringOn ? "ON" : "OFF"));
}
尽管参数值被转换为字符串,但它将在 SQL 服务器端重新转换/检查,因此在应用程序端进行验证是必要的。