2017-09-23 47 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. 
相關問題