使用带有对象实例的DI容器解析对象

时间:2015-06-08 15:19:07

标签: c# dependency-injection light-inject

我有一个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容器,以可维护的方式执行此操作的正确方法是什么,考虑到依赖链对于复杂方法可能会花费很长时间?

修改 我使我的用例更加清晰(改变了实现IUser的类)。

2 个答案:

答案 0 :(得分:0)

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));

答案 1 :(得分:0)

可以使用工厂模式开发。

通过这种方法,您可以使用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网页。有一章名为&#34; Dependency Constructors&#34;了解更多信息。 http://www.lightinject.net/#toc16

希望有所帮助