Activator.CreateInstance()麻烦

我有一个工厂应该创建在运行时从类Fooinheritance的对象。 我认为System.Activator.CreateInstance的返回类型与它创建的对象的类型相同,但从以下错误消息判断,其返回类型是Object。

错误1无法将类型’object’隐式转换为’cs_sandbox.Foo’。 存在显式转换(您是否缺少演员?)F:\ projects \ cs_sandbox \ Form1.cs 46 24 cs_sandbox

好吧,也许我错过了一个演员,但是

return (t)System.Activator.CreateInstance(t); 

导致另一条错误消息 – 我必须承认 – 这对我没有意义:

错误1找不到类型或命名空间名称’t’(您是否缺少using指令或程序集引用?)F:\ projects \ cs_sandbox \ Form1.cs 45 25 cs_sandbox

这是我的代码:

 class Foo { } class FooChild1 : Foo { } class FooChild2 : Foo { } class MyFactory { public static Foo CreateInstance(string s) { Type t; if (s.StartsWith("abcdef")) { t = typeof(FooChild1); return System.Activator.CreateInstance(t); } else { t = typeof(FooChild2); return System.Activator.CreateInstance(t); } } } 

我该如何修复此代码? 或者,如果它不可修复,那么在运行时创建从特定类inheritance的对象的其他方法是什么?

您需要将返回的对象FooFoo类型。 将它强制转换为变量中定义的类型是没有意义的。 它应该由编译器知道,因为通过inheritance层次结构的整个点是满足编译器的静态类型检查。

 return (Foo)System.Activator.CreateInstance(t); 

有一个通用版本, System.Activator.CreateInstance ,它创建一个已知类型(不是类型变量,但是类型参数或静态已知类型,在后一种情况下,它没有太大意义):

 return System.Activator.CreateInstance(); 

我必须在激活后使用UnWrap()方法,如MSDN中所述:

 // Creates an instance of MyType defined in the assembly called ObjectHandleAssembly. ObjectHandle obj = domain.CreateInstance("ObjectHandleAssembly", "MyType"); // Unwrapps the proxy to the MyType object created in the other AppDomain. MyType testObj = (MyType)obj.Unwrap(); 

如MSDN所述 。 此外,我不得不使用这样的参数:

  ObjectHandle obj = domain.CreateInstance("Other.Assembly.Name", "Full.Class.Namespace.ClassName"); 

更改代码后

只需将结果投射到Foo就好了

 return System.Activator.CreateInstance(t) as Foo; 

要么

 return (Foo)System.Activator.CreateInstance(t); 

第一个更健壮,因为在不可能的情况下你不会得到exception。 它只会返回null 。 但这取决于你想要什么。

在更改代码之前

你尝试过generics吗?

 public static OutType CreateInstance(string s) { Type t; if (s.StartsWith("abcdef")) { t = typeof(Bar); return System.Activator.CreateInstance(t) as OutType; } else { t = typeof(Meh); return System.Activator.CreateInstance(t) as OutType; } } 

但你确实有问题。 在您现有的静态方法中,您试图以任何方式返回与Foo无关的BarMeh 除非您的方法还返回一个对象或一个共同的祖先类型(如在转换中),否则这将始终是一个例外。

要控制更多内部类型,您可以定义方法在内部使用的多个generics类型。

我想你应该这样做:

 public static Foo CreateInstance(string objectIdentifer) { if (objectIdentifier == "Child1") { return (Foo)Activator.CreateInstance("Foo.FooChild1, FooChild1"); } else { return (Foo)Activator.CreateInstance("Foo.FooChild1, FooChild2"); } } 

我的观点是,在此代码中,CreateInstance方法没有直接引用包含FooChild1和FooChild2的程序集。 在原始代码中,您通过显式命名FooChild1和FooChild2来创建类型,因此您可能只是新建它们而不是激活它们。

你能理解这个吗?

我认为正确的是:

 public static Foo CreateInstance(string objectIdentifer) { if (objectIdentifier == "Child1") { return (Foo)Activator.CreateInstance(Type.GetType("Foo.FooChild1, FooChild1")); } else { return (Foo)Activator.CreateInstance(Type.GetType("Foo.FooChild1, FooChild2")); } } 

希望能帮到你

也许有点晚,但如果我不知道类型(如果你建立自己的代码分析器)我使用Convert.ChangeType

  string original = "1"; object value; value = Convert.ChangeType(original, typeof(int)); 

typeof(int)可以是使用object.GetType();你不知道的任何类型。