2017-09-23 49 views
1

使用Spring4D,我想建立一个容器,委托服务解决方案到另一个容器,如果它不能解析服务 - 这些方针的东西:如何将Container1.Resolve <T>委派给Container2.Resolve <T>,如果Container1无法解析T?

function TContainer.Resolve<T>: T; 
begin 
    if not TryResolve<T>(Result) then 
    Result := OtherContainer.Resolve<T>; 
end; 

这可能吗?如果是,如何?


我离开了我的例子项目作为StackOverflow上不会让我张贴,否则这个问题:“它看起来像你的职位主要是代码,请添加一些更多的细节。”

回答

1

有所谓subdependency解析器(未来的版本将只调用它们的类型解析)用于处理特定类型或类型模式的容器内(比如能够解决在正在注册牛逼的东西TArray<T>IList<T>)。

您可以实现自己的检查类型是否不在您将此解析器附加到此容器的容器中,然后将此类型的解析链委派给其他容器。

下面是一些示例代码如何实现这一(而不释放对象)

uses 
    Spring, 
    Spring.Container, 
    Spring.Container.Core, 
    System.SysUtils; 

type 
    TFoo = class 

    end; 

    TBar = class 
    private 
    fFoo: TFoo; 
    public 
    constructor Create(const foo: TFoo); 
    property Foo: TFoo read fFoo; 
    end; 

    TSubContainerResolver = class(TInterfacedObject, ISubDependencyResolver) 
    private 
    fContainer: TContainer; 
    fSubContainer: TContainer; 
    public 
    constructor Create(const container, subContainer: TContainer); 

    function CanResolve(const context: ICreationContext; 
     const dependency: TDependencyModel; const argument: TValue): Boolean; 
    function Resolve(const context: ICreationContext; 
     const dependency: TDependencyModel; const argument: TValue): TValue; 
    end; 

{ TBar } 

constructor TBar.Create(const foo: TFoo); 
begin 
    fFoo := foo; 
end; 

{ TSubContainerResolver } 

constructor TSubContainerResolver.Create(const container, subContainer: TContainer); 
begin 
    fContainer := container; 
    fSubContainer := subContainer; 
end; 

function TSubContainerResolver.CanResolve(const context: ICreationContext; 
    const dependency: TDependencyModel; const argument: TValue): Boolean; 
begin 
    Result := not fContainer.Kernel.Registry.HasService(dependency.TypeInfo) 
    and fSubContainer.Kernel.Resolver.CanResolve(context, dependency, argument); 
end; 

function TSubContainerResolver.Resolve(const context: ICreationContext; 
    const dependency: TDependencyModel; const argument: TValue): TValue; 
begin 
    Result := fSubContainer.Kernel.Resolver.Resolve(context, dependency, argument); 
end; 

procedure ScenarioOne; 
var 
    c1, c2: TContainer; 
    b: TBar; 
begin 
    c1 := TContainer.Create; 
    c2 := TContainer.Create; 
    c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1, c2)); 

    // dependency in subcontainer 
    c1.RegisterType<TBar>; 
    c1.Build; 
    c2.RegisterType<TFoo>; 
    c2.Build; 

    b := c1.Resolve<TBar>; 
    Assert(Assigned(b.fFoo)); 
end; 

procedure ScenarioTwo; 
var 
    c1, c2: TContainer; 
    b: TBar; 
begin 
    c1 := TContainer.Create; 
    c2 := TContainer.Create; 

    c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1, c2)); 
    c2.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c2, c1)); 

    // type in subcontainer but dependency in parent container 
    c1.RegisterType<TFoo>; 
    c1.Build; 
    c2.RegisterType<TBar>; 
    c2.Build; 

    b := c1.Resolve<TBar>; 
    Assert(Assigned(b.fFoo)); 
end; 

begin 
    ScenarioOne; 
    ScenarioTwo; 
end. 
相关问题