使用带有对象实例的 DI 容器解析对象
Resolve object using DI container with object instance
我有一个 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)。
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));
可以使用工厂模式开发
通过这种方法,您可以通过工厂获取特定用户的实例,为每个具体 class。
使用显式服务注册:
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 网页。有一个名为 "Dependency Constructors" 的章节以获取更多信息。 http://www.lightinject.net/#toc16
希望对您有所帮助
我有一个 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)。
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));
可以使用工厂模式开发
通过这种方法,您可以通过工厂获取特定用户的实例,为每个具体 class。
使用显式服务注册:
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 网页。有一个名为 "Dependency Constructors" 的章节以获取更多信息。 http://www.lightinject.net/#toc16
希望对您有所帮助