3

我有一个工厂,它应该在运行时创建从类 Foo 继承的对象。我会认为 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);
        }
    }
}

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

4

5 回答 5

10

您需要将返回的对象转换为Foo类型。将其强制转换为变量中定义的类型是没有意义的。编译器应该知道这一点,因为通过继承层次进行强制转换的重点是满足编译器的静态类型检查。

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

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

return System.Activator.CreateInstance<FooChild1>();
于 2009-09-27T21:53:36.740 回答
2

激活后我必须使用 to 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");
于 2012-10-15T09:51:00.643 回答
1

更改代码后

只需将您的结果投给Foo喜欢

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

或者

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

第一个更健壮一些,因为如果无法进行强制转换,您不会得到异常。它会简单地返回null。但这取决于你想要什么。

在您更改代码之前

你试过泛型吗?

public static OutType CreateInstance<OutType>(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;
    }
}

但是你确实有问题。在您现有的静态方法中,您试图返回Bar并且与任何方式Meh都没有关系Foo。这将始终是一个例外,除非您的方法还返回一个对象或一个共同的祖先类型(如在强制转换中)。

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

于 2009-09-27T21:57:57.590 回答
0

我认为正确的是:

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

希望能帮到你

于 2010-03-03T04:17:40.033 回答
0

我认为你应该这样做:

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 来创建一个类型,因此您最好只新建它们而不是激活它们。

你能理解这个吗?

于 2009-09-27T22:12:46.763 回答