4

構造マップ レジストリのジェネリック ファクトリ クラスでメソッドを使用しようとしています。通常、ファクトリ メソッドを使用して型を登録するときは、次のようにします。

For<Foo>().Use(x => new FooFactory().GetFoo());

ジェネリック型を登録する場合は、次のようになります。

For(typeof(ISomeGeneric<>)).Use(typeof(SomeGeneric<>));

2 つを組み合わせて、ジェネリック ファクトリ メソッドからジェネリック型を取得するにはどうすればよいですか? 私はそれが次のようなものであるべきだと思います:

For(typeof(IFoo<>)).Use(typeof(x => new FooFactory<>().Create(someParameter));

これはちょうど与える

"Cannot convert lambda expression to type object because it is not a delegate type" 

エラー。いろいろな組み合わせを試しましたがだめです。何か案は?

ありがとう。

4

1 に答える 1

0

これは可能ですが、可能であれば代替手段を探します。問題は、オープンジェネリックを使用するには、リフレクションを使用する必要があることです。これは、パフォーマンスが低下することを意味します。

public class FooRegistry:Registry
{
    public FooRegistry()
    {
        For(typeof(IFoo<>)).Use(x =>
        {
            var ParamType = x.BuildStack.Current.RequestedType
                             .GetGenericArguments()[0];
            return BuildUsingFooFactory(ParamType);
        });
    }

    private object BuildUsingFooFactory(Type paramType)
    {
        var factoryType = typeof (FooFactory<>).MakeGenericType(new[] {paramType});
        var createMethod = factoryType.GetMethod("Create");
        object factory = Activator.CreateInstance(factoryType);
        return createMethod.Invoke(factory, new[] {"SomeParameterString"});
    }
}

public class FooFactory<T>
{
    public IFoo<T> Create(string param)
    {
        return new Foo<T>();
    }

}

public interface IFoo<T>
{
}

public class Foo<T> : IFoo<T>
{   
}

あなたが順番にやっていることは次のとおりです。

  1. 要求されたジェネリック引数が何であるかを調べます。(パラメータタイプ)
  2. ファクトリ (factoryType) の非オープン ジェネリック型を作成します。
  3. そこから create メソッドを取得します。(作成方法)
  4. Activator (ファクトリー) を使用してファクトリーのインスタンスを作成する
  5. some パラメータを使用して、ファクトリ インスタンスの create メソッドを呼び出します。

StructureMap は、出力を適切なインターフェイスにキャストします。

より良い解決策

IFoo を直接使用する代わりに、IFooFactory を使用します。これにより、IFooFactory<> への一般的なマッピングがオープンになり、よりクリーンになります。次に、オブジェクトを生成するために必要な FooFactory のタイプを取得します。

public class FooRegistry:Registry
{
    public FooRegistry()
    {
        For(typeof (IFooFactory<>))
            .Use(typeof (FooFactory<>))
            .CtorDependency<string>("connection")
            .Is("SomeConnectionString");
    }
}


public interface IFooFactory<T>
{
    IFoo<T> CreateInstance();
}

public class FooFactory<T> : IFooFactory<T>
{
    public FooFactory(string connection)
    {
    } 

    public IFoo<T> CreateInstance()
    {
        return new Foo<T>();
    }
}

public interface IFoo<T>
{
}

public class Foo<T> : IFoo<T>
{   
}
于 2014-03-14T03:34:47.653 に答える