0

DryIoc と ExpressMapper を使用しています。

ExpressMapper を別のクラス内にラップし、ある時点でそれを使用して、パラメーター化されたコンストラクターを持つ型にマップする必要があります。実際には、ビュー モデルをビジネス モデルにマッピングするときです。パラメータは、リポジトリ クラスのインスタンスです。

TDD を使用すると、私の Mapper クラスは次のようになりました (Func を受け入れるコンストラクターに注意してください)。

public class Mapper<T1, T2> : IMapper<T1, T2>
{
    private readonly MappingServiceProvider _mapper;

    public Mapper()
    {
        _mapper = new MappingServiceProvider();
        _mapper.Register<T1, T2>();
    }

    public Mapper(Func<T2> func)
    {
        _mapper = new MappingServiceProvider();
        _mapper.Register<T1, T2>().Instantiate((t1) => func());
    }

    public T2 Map(T1 t)
    {
        return _mapper.Map<T1, T2>(t);
    }
}

したがって、次のように Ioc を使用しようとしました。

        Func<IActivitiesModel>factoryActivitiesModel = () => container.Resolve<IActivitiesModel>();
        container.Register(Made.Of(() => factoryActivitiesModel));
        // () => new ActivitiesModel(container.Resolve<IActivityRepository>(IfUnresolved.Throw)
        container.Register<IMapper<ActivitiesViewModel, IActivitiesModel>, Mapper<ActivitiesViewModel, IActivitiesModel>>(Reuse.Singleton, Made.Of(
            () => new Mapper<ActivitiesViewModel, IActivitiesModel>(Arg.Of<Func<IActivitiesModel>>())
        ));

しかし、それはしませんでした。

Unable to use null factory object with factory method ActivitiesMVC.Ioc.<>c__DisplayClass4_0::System.Func`1[ActivitiesLogic.Models.IActivitiesModel] factoryActivitiesModel when resolving: Func<ActivitiesLogic.Models.IActivitiesModel>.

とにかく、その後さまざまなアプローチを試みましたが、どれもうまくいかないようでした。

コンテナーを静的なシングルトンとして格納し、マッパーがそれに依存することを避けたいです (マッパーは Ioc に依存しないままにしておきたいです)。

どうすれば達成できますか?

EDIT : 現在の解決策 (悪い静的シングルトンを使用)

public class Ioc
{
    public class Factory<T> : IFactory<T>
    {
        public T Create()
        {
            return Container.Resolve<T>();
        }
    }

    private static Lazy<Container> _container;

    public static Container Container => _container.Value;

    static Ioc()
    {
        _container = new Lazy<Container>(GetContainer);
    }

    static private Container GetContainer()
    {
        var container = new Container(rules => rules
            //.WithoutThrowOnRegisteringDisposableTransient()
            .WithTrackingDisposableTransients());
        container.Register(Made.Of(() => new ActivityController(Arg.Of<IMapper<ActivitiesViewModel, IActivitiesModel>>())));
        container.Register<ILabContext, LabContext>(new SingletonReuse());
        container.Register<IActivityRepository, ActivityRepository>(new SingletonReuse());
        container.Register<IActivitiesModel>(made: Made.Of(() => new ActivitiesModel(Arg.Of<IActivityRepository>())));
        container.Register(typeof(IFactory<>), typeof(Factory<>), new SingletonReuse());
        container.Register<IMapper<ActivitiesViewModel, IActivitiesModel>, Mapper<ActivitiesViewModel, IActivitiesModel>>(Reuse.Singleton, Made.Of(
            () => new Mapper<ActivitiesViewModel, IActivitiesModel>(Arg.Of<IFactory<IActivitiesModel>>())
        ));
        container.Register<IMapper<ActivitiesModel, ActivitiesEntity>, Mapper<ActivitiesModel, ActivitiesEntity>>(new SingletonReuse(), Made.Of(
            () => new Mapper<ActivitiesModel, ActivitiesEntity>()
        ));

        return container;
        ;
    }
}
4

1 に答える 1

1

まず、私は ExpressMapper に詳しくないので、サンプル コードのみに基づいて支援を試みます。

私が理解したように、アクティビティモデル、リポジトリ、vm など、および Func 依存関係に依存する IMapper / Mapper 実装を登録したいと考えています。別の詳細は、マッパーには 2 つのコンストラクターがあるため、Made.Of を使用しようとした可能性があります。

ただし、Made.Of は、Func デリゲートではなく Expression> で機能します。それが私が信じている例外の理由です。

このセットアップを試してください:

container.Register(typeof(IMapper<,>), typeof(Mapper<,>), Reuse.Singleton,
    // will select second constructor with Func parameter
    made: FactoryMethod.ConstructorWithResolvableArguments);

// normal model registrations, no need to use Made.Of
// if implementations have single constructor,
// othetwise try use the same made as for Mapper.
container.Register<IActivitiesModel, ActivitiesModel>();
// ... the same way register repository, vm, etc. 

コードで複数のコンストラクターを使用する状況が一般的である場合 (デフォルトの ctor を持つことが ExpressMapper の要件である可能性がありますか?)、コンテナーごとに自動コンストラクター選択をグローバルに構成できます。

container = new Container(rules => rules
    .With(FactoryMethod.ConstructorWithResolvableArguments));
于 2016-03-03T20:15:46.247 に答える