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

MSDNで説明されているように、アクティブ化した後にUnWrap()メソッドを使用する必要がありました。

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

しかし、あなたには問題があります。既存の静的メソッドで返そうとしているのですがBarMehそれはまったく関係ありませんFoo。メソッドがオブジェクトまたは共通の祖先タイプ(キャストの場合など)も返さない限り、これは常に例外になります。

さらに多くの内部型を制御するために、メソッドが内部で使用する複数のジェネリック型を定義できます。

于 2009-09-27T21:57:57.590 に答える
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を含む1つまたは複数のアセンブリを直接参照していないことです。元のコードでは、FooChild1とFooChild2に明示的に名前を付けて型を作成するため、アクティブ化するのではなく、単に新しいものにすることもできます。

これはあなたにとって意味がありますか?

于 2009-09-27T22:12:46.763 に答える
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 に答える