1

オブジェクトをインスタンス化する汎用ルーチンをプログラム内に作成しようとしています。new Object() の呼び出しを実際に担当するルーチンは、インスタンス化する必要があるファクトリ内の別のアセンブリ内にあります。

namespace ExternalLib
{
    class Object1Factory
    {
        public Object1 getObject1()
            //...
    }
    class Object2Factory
        // Same implementation as Object1Factory
}

適切なルーチンを呼び出してオブジェクトを「新規作成」できるルーチンをアプリケーションに提供しようとしています。

namespace MyApp
{
    class Program
    {
        static void Main()
            //...
        static Object getNewObject(string typeName)
        {
            //This is where I have problems
        }
    }
}

外部ライブラリと自分のプログラムの両方のソース コードにアクセスできますが、アーキテクチャ全体を書き直すにはコストがかかりすぎます。

私が試したこと:私の最初のアイデアは、ファクトリおよび/またはファクトリルーチンでカスタム属性を使用し、リフレクションを使用してメソッドを取得してからメソッドを呼び出すことでした。私はもともと署名private static T getNew<T>()を使用していて、型パラメーターで switch ステートメントを使用しようとしていましたgetNewObject(string typeName)が、より簡単になることに気付きました。ファクトリには同じコンストラクタ シグネチャがありますが、継承リンクはありません。

要約すると、オブジェクトを作成するルーチンは別のアセンブリのファクトリにあります。これらのルーチンを自動的に呼び出して、型に基づいてオブジェクトを取得するにはどうすればよいですか?

4

3 に答える 3

4

この道を進みたい場合、すべてのファクトリ メソッドを「ObjectFactory」などと呼ばれる 1 つのファクトリ クラスに入れることができますか?

Type t = typeof(OtherAssembly.ObjectFactory);

MethodInfo m = t.GetMethods().Where(a => a.ReturnType.Name == typeName).FirstOrDefault();

return m.Invoke(null, new object[] { /* PARAMETERS */ });


編集- ファクトリ クラスを分離しておくことを好むというジェームズの質問に対するコメントへの応答:

(以下のMartinのアイデアを使用し、すべてのFactoryクラスが「[Type]Factory」という名前であることに依存しています)

(ファクトリ クラスには非静的メソッドもあります)

Type t = Type.GetType(String.Format("OtherAssembly.{0}Factory", typeName));

var myFactory = Activator.CreateInstance( t );

MethodInfo m = t.GetMethods().Where(a => a.ReturnType.Name == typeName).FirstOrDefault();

return m.Invoke(myFactory, new object[] { /* PARAMETERS */ });
于 2012-05-23T15:34:34.433 に答える
2

質問に何かが欠けているかもしれませんが、これを使用するだけで何が問題なのですか:

static Object getNewObject(string typeName)
{
    var type = Type.GetType(typeName);
    return Activator.CreateInstance(type);      
}

typeName が Object1 で、Object1Factory を取得したい場合は、少し文字列操作とリフレクションを使用し、リフレクションを使用してファクトリの getObject1() メソッドを呼び出します。

「MyNameSpace.Object1、Object1Assembly」のように typeName を渡すことができる場合、関連するアセンブリからロードされます。

于 2012-05-23T15:28:40.807 に答える
0

署名を次のように変更した場合、純粋にあなたが試したことに応じて:

static T GetNew<T>() where T : new()
{
    // Then you can do this:
    return new T();
}

パラメーターなしのパブリック コンストラクターの一般的な制約を type に配置しTます。ただし、呼び出しコードは次のようになるため、これは無意味です。

var obj = GetNew<MyClass>();

通常は次のようになります。

var obj = new MyClass();

したがって、私はそれを解決策として採用するつもりはありませんが、それは機能し、switch ステートメントの必要性を否定していたでしょう。

于 2012-05-23T15:23:37.517 に答える