2009-11-12 98 views
11

我有在C#中的以下内容:如何在运行时生成未知类型的实例?

string typename = "System.Int32"; 
string value = "4"; 

论文两个字符串应采取生成指定的类型与所指定的值的对象...

的结果应该是:

object o = CreateUnknownType(typename, value); 
... 
Int32 test = (Int32)o; 
+4

而你的问题是?为什么试图创建一个未知的,如果你打算将它转换成一个已知的类型呢? – Lazarus 2009-11-12 14:24:35

+6

问题是:如何在运行时生成未知类型的实例?没关系为什么或者没有,我只想知道它是否可能 – haze4real 2009-11-12 14:52:34

+2

那很容易,是的,这是可能的。这是否可行?可能不会。当你的例子没有意义时,问一些背景是不合理的? – Lazarus 2009-11-12 16:20:28

回答

20

这是你在想什么?

object result = Convert.ChangeType("4", Type.GetType("System.Int32")); 
+0

是的,这就是它,谢谢 – haze4real 2009-11-12 14:40:12

1

你的逻辑在这里似乎有点缺陷。很明显,如果你以后直接将对象转换为实际的类型,那么你必须知道类型。

如果还有其他的东西在这个问题上没有,请详细说明,也许有一个比简单的更合适的答案,“这没有多大意义。”

0

这看起来像Int32.Parse(字符串)的工作。但要同意其他人的看法,这似乎是“独一无二的”,应该可能会认为手套。

15

如上所述,这太宽泛且无法一般地解决。

这里有一些选择:

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"确定)显示了一般问题是多么荒谬。有一些建设/转换是无法完成的。

您可能想要重新考虑您尝试解决的问题以避免这种恶作剧。

+0

也许我应该,谢谢你解释的可能性... – haze4real 2009-11-12 14:47:06

3

通过创建一个名字你知道一个类型的实例(并且应该有一个默认的构造函数):

string typeName = "System.Int32"; 
    Type type = Type.GetType(type); 
    object o = Activator.CreateInstance(type); 

从字符串解析值显然只为一组有限的工种。你可以

  • 使用Convert.ChangeType通过PhilipW
  • 建议
  • 或也许创建 Dictionary<Type,Func<string,object>> 它映射已知类型已知的解析 功能
  • 或使用反射来调用 解析(string)方法 假设有一个:

    string valueText = "4"; 
        MethodInfo parseMethod = type.GetMethod("Parse"); 
        object value = parseMethod.Invoke(null, new object[] { valueText }); 
    
  • 或者您可以使用由.NET 组件模型提供的基础结构 。您可以获取组件的 型转换器,并使用 这样的:

    TypeConverter converter = TypeDescriptor.GetConverter(type); 
        object value = converter.ConvertFromString(valueText); 
    
0

使用后:

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); 
    } 
} 

希望这有助于。

1

也许你有一组不同的类型,所有这些都实现了一个已知的接口?例如,如果你有几个不同的用户控件,并希望将其中的一个加载到一个容器中,则每个人都可能实现IMyWobblyControl(一个已知接口),但在运行时可能不知道它们要加载哪些内容,可能来自阅读来自某种形式的配置文件的字符串。

在这种情况下,您需要使用反射从类似完整程序集名称加载实际类型,然后将其转换为已知类型以使用它。

当然,你需要确保你的代码处理无效的转换,组装没有发现任何有可能通过的摇晃,因为这东西一起去其他异常...

0

这里有一个具体的涉及Azure SQL Federations的问题的示例...根据密钥范围将数据分割为单独的数据库。

的键范围的类型有:

SQL/的.Net SQL类型/CLR的.Net

INT/SqlInt32 /的Int32,可空

BIGINT/SqlInt64/Int64类型,Nullable

UNIQUEIDENTIFIER/SqlGuid/Guid,Nullable

VARBINARY(n)时,最大n 900/SqlBytes,SqlBinary /字节[]

理想情况下,C#函数PARAM可以采取以下的.Net SQL类型或CLR .NET类型但沉降上类型的只是一个类别很好。

会有“对象”类型参数是要走的路吗?而且,是否有一种可行的方法来识别类型并相应地进行转换?

的概念是一样的东西:

公共无效FN(obj对象,字符串fedName,串DISTNAME,布尔filteringOn)

{

...弄清楚什么类型obj是保证它是可接受的类型之一...

string key = obj.toString();

return string.Format(“USE FEDERATION {0}({1} ='{2}')WITH RESET,FILTERING = {3}”,fedName,distName,key,(filteringOn?“ON”:“ OFF“));

}

虽然PARAM值被转换为字符串,将重铸/检查上的SQL服务器侧,从而验证它上的应用程序侧是希望的。