C# 使用具有对象实例的DI容器解析对象

C# 使用具有对象实例的DI容器解析对象,c#,dependency-injection,light-inject,C#,Dependency Injection,Light Inject,我有一个ICommand接口和使用构造函数注入的依赖项的任务。依赖项使用不同的构造函数,因此它们必须由请求本身解决。我想告诉我的容器如何在正在解析的特定上下文中解析某些依赖项 interface ICommand { string Do(); } interface IUser { string Name { get; } } class Welcome : ICommand { IUser _user; public Welcome(IUser user)

我有一个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");
var container=new LightInject.ServiceContainer();
容器。注册(“欢迎”);
现在,我想在我的请求中这样做:

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();
}
使用(var scope=container.BeginScope())
{
//我需要告诉我的容器如何在需要时解决这个依赖关系
//但下面的方法并不存在
scope.ResolverForScope(()=>createIUser(请求));
var命令=container.GetInstance(命令);
return命令.Do();
}
考虑到复杂方法的依赖链可能会变得很长,对于任何DI容器,以可维护的方式执行此操作的正确方法是什么

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

静态类作用域ContainerExtensions
{
类作用域容器
{
字典工厂=新字典();
公共无效登记簿(Func工厂)
T:在哪里上课
{
添加(typeof(T),new Lazy(factory));
}
公共事务解决方案
{
返回((惰性)工厂[typeof(T)])。值;
}
}
用于(此IServiceContainer容器)的公共静态无效
{
if(!container.CanGetInstance(typeof(ScopedContainer),“”)
{
container.Register(新PerScopeLifetime());
}
Register(sf=>sf.GetInstance().Resolve());
}
public static void ResolverForCurrentScope(此IServiceContainer容器,Func工厂)
T:在哪里上课
{
var scope=container.ScopeManagerProvider.GetScopeManager().CurrentScope;
container.GetInstance().Register(()=>
{
var实例=工厂(容器);
var disposable=实例作为IDisposable;
if(一次性!=null)
范围.TrackInstance(一次性);
返回实例;
});
}
注册:

container.UseScopedContainerFor<IUser>();
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();
}
container.UseScopedContainerFor();
使用范围:

container.ResolverForCurrentScope<IUser>(fac => fac.GetInstance<OAuthUserFactory>().Create(fac.GetInstance<IOAuthService>(), Request));
container.ResolverForCurrentScope(fac=>fac.GetInstance().Create(fac.GetInstance(),Request));

它可以通过使用工厂模式进行开发

使用这种方法,您可能能够获得特定用户的实例,并使用工厂为每个具体类提供实例

使用显式服务注册:

container.UseScopedContainerFor<IUser>();
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();
}
var container=new LightInject.ServiceContainer();
//注册传递用户实例的命令
container.Register(factory=>newwelcome(factory.GetUser(request));
使用(var scope=container.BeginScope())
{        
var命令=(ICommand)container.GetInstance();
return命令.Do();
}
我刚才提到了LightInjectWeb页面。有一章叫做“依赖项构造函数”,以获取更多信息


希望它有帮助

在您的注册中,我会有一个开关,表示如果远程使用此对象实例化,如果本地使用另一个对象实例化。更好的是,我会有一个方法使用远程实例化您的所有对象,另一个方法使用本地实例化您的所有对象……但注册开关不会禁用一个吗整个应用程序实例的访问方法?应该是每个应用程序实例的访问方法。是的。如果我理解正确,你只需要一个远程实例和一个本地实例?或者你需要每个应用程序实例都可以使用它们吗?我需要它们,我已经编辑了这个问题,以便更清楚地了解我想要做什么。我个人不知道“我认为您没有解决问题的正确方法。我会使用策略模式和工厂模式来获取正确的信息,并创建一个新的
IUser
实现。您不会根据实现来决定要做什么……远程、sql和凭据信息必须从其他方面获取。这是非常重要的。”实际上,这是正确的方法,但我担心对于长依赖链来说,这听起来太冗长了。想象一下像
SendInvitationWithReferenceLinkFromUser(IReferalService ref,IUser user,IEmailService)
这样的命令需要大量依赖项的
IReferalService
IEmailService
(包括
IReferalService
所需的
IUser
)。我也不想为每个请求注册一个工厂,因为我认为在容器中注册所有内容可能比仅使用它要花费更长的时间。您无法新建接口
container.ResolverForCurrentScope(()=>new IUserInstance());
谢谢您的评论,我已经编辑了我的解决方案以使用
IServiceFactory