2

コンストラクターによって注入された依存関係を使用している ICommand インターフェイスとタスクがあります。依存関係は異なるコンストラクターを使用しているため、リクエスト自体で解決する必要があります。コンテナが解決されている特定のコンテキストでいくつかの依存関係を解決する方法をコンテナに伝えたいです。

interface ICommand
{
    string Do();
}

interface IUser
{
    string Name { get; }
}

class Welcome : ICommand
{
    IUser _user;
    public Welcome(IUser user)
    {
        _user = user;
    }

    public string Do()
    {
        return "Hello, "+_user.Name;
    }
}

class OAuthUser : IUser
{
    // use remote service to get data
    public OAuthUser (IOAuthService service, JsonWebToken token)
    {
        // to be implemented
    }
}

class TemporaryTokenUser : IUser
{
    // use sql to check if user has temporary token
    public TemporaryTokenUser (IDbConnection db, string token)
    {
        // to be implemented
    }
}

class UserPasswordUser : IUser
{
    // try authenticating user with credentials
    public UserPasswordUser (IAuthService svc, string user, string password)
    {
        // to be implemented
    }
}

インターフェイスとクラスを LightInject に登録しました。

var container = new LightInject.ServiceContainer();
container.Register<ICommand, Welcome>("welcome");

今、私は自分のリクエストで次のようなことをしたいと思っています:

using (var scope = container.BeginScope())
{
    // I need to tell my container how to resolve this dependency in case its needed
    // but method below does not exist
    scope.ResolverForScope<IUser>(()=>createIUser(request));
    var command = container.GetInstance<ICommand>(command);
    return command.Do();
}

依存関係チェーンが複雑なメソッドに対して非常に長くなる可能性があることを考えると、DI コンテナーでこれを保守可能な方法で行う正しい方法は何でしょうか?

EDIT ユース ケースをより明確にしました (IUser を実装するクラスを変更しました)。

4

2 に答える 2

1

Factoryパターンを使用して開発される場合があります。

このアプローチでは、特定のユーザーのインスタンスを Factory で取得して、各具象クラスにインスタンスを提供できる場合があります。

明示的なサービス登録の使用:

var container = new LightInject.ServiceContainer();
//register your command passing a user instance
container.Register<ICommand>(factory => new Welcome(factory.GetUser<IUser>(request)));

using (var scope = container.BeginScope())
{        
    var command = (ICommand)container.GetInstance<ICommand>();
    return command.Do();
}

LightInject の Web ページを参照しました。詳細については、「依存関係コンストラクター」という章があります。http://www.lightinject.net/#toc16

それが役に立てば幸い

于 2015-06-08T16:54:59.527 に答える
1
static class ScopedContainerExtensions
{
    class ScopedContainer
    {
        Dictionary<Type, object> factories = new Dictionary<Type,object>();
        public void Register<T>(Func<T> factory)
            where T: class
        {
            factories.Add(typeof(T), new Lazy<T>(factory));
        }

        public T Resolve<T>()
        {
            return ((Lazy<T>)factories[typeof(T)]).Value;
        }
    }

    public static void UseScopedContainerFor<Service>(this IServiceContainer container)
    {
        if (!container.CanGetInstance(typeof(ScopedContainer), ""))
        {
            container.Register<ScopedContainer>(new PerScopeLifetime());
        }
        container.Register<Service>(sf=>sf.GetInstance<ScopedContainer>().Resolve<Service>());
    }

    public static void ResolverForCurrentScope<T>(this IServiceContainer container, Func<IServiceFactory, T> factory)
        where T : class
    {
        var scope = container.ScopeManagerProvider.GetScopeManager().CurrentScope;
        container.GetInstance<ScopedStorage>().Register<T>(() =>
        {
            var instance = factory(container);
            var disposable = instance as IDisposable;
            if (disposable != null)
                scope.TrackInstance(disposable);
            return instance;
        });
    }

登録:

container.UseScopedContainerFor<IUser>();

使用範囲:

container.ResolverForCurrentScope<IUser>(fac => fac.GetInstance<OAuthUserFactory>().Create(fac.GetInstance<IOAuthService>(), Request));
于 2015-06-08T16:41:57.263 に答える