SimpleInjector. How to resolve instances which has parameters that could be evaluated only in runtime

I have a lot of objects in my program that are created at runtime with at least 1 parameter. There are many nested classes where a new data is evaluated, which is necessary for next inner instances.

At first, let me briefly describe the structure, and then I’ll provide you with the simplified example.

Structure description.

  1. An user sends string request ->
  2. Program determines IRequestContext and ICommand ->
  3. ICommand.Execute(IRequestContext) is called ->
  4. The execution creates IStep[] and IPlan(IStep[]) via factory and sends it to scheduler ->
  5. At a certain time scheduler launches IPlan with the IRequestContext.
  6. IPlan executes step by step by calling IObservable<Report> IStep.Make(IRequestContext) ->
  7. An implementations of IStep contains buffer instances to share result of their execution in scope of current plan. It’s not returned but it’s necessary to produce final Report, but not only for this purpose. Buffer can’t have interface cause it’s a storage of data after all.
  8. Report contains enum Result and IMessageBuilder. IMesageBuilder has only 1 method Build().

Details

Each class has a lot of dependencies by itself such as interfaces for work with database, localization, communication API. This dependencies are registred at the composition root. They are not problem in this case.

An instance of IRequestContext is created at the runtime for each user request. IStep, IMessageBuilder and all sorts of buffers depend on it. Therefore I can’t just register SomeMessageBuilder, because the necessary data for a builder is being created during the step execution. And different requests can’t share the same instance of message builder or buffer.

For each implementation of IMessageBuilder there will be different count and types of parameters. That is why I can’t change interface to accept this entities like IMessageBuilder.Build(Entity1, Entity2, ...). Therefore I have to create and register factories for each implementation of IMessageBuilder. As a result each IStep implementation has dependency from a IFactory<T1,T2,...,IMessageBuilder>.

Each IPlan implementation has it’s own factory which creates unique combination of steps. Furthermore I use implementation of composite pattern for steps such as CompositeStep(IStep[] step) : IStep. Therefore I have to register factory for each implementation of IStep, and I have to register factory for each CompositeStep which consists of different steps.

Simplified example

Please keep in mind that I have dozen of different IPlan implementations which can use same steps.

Some interfaces and class for clarification.

public interface IPlan<in TContext,out TReport>{
  IObservable<TReport> Execute(TContext context);
  bool IsReadyToGoNext(TReport report);
}
public interface IStep<in TContext,out TReport>{
  IObservable<TReport> Make(TContext context);
}
public interface IFactory<in T1, out TObject>
{
  TObject Create(T1 param);
}

public interface IMessageBuilder{
  SendMessage Build();
}
public class CreateMessageBuilder : LocalizedMessageBuilder, IMessageBuilder
{
  public CreateMessageBuilder(long chatId, CultureInfo info
  , ILocalizationProvider localizationProvider, int minSymbols, int maxSymbols)
  {...}
  public  void SetUser(UserRepresentation representation){...};
  public void SetSirena(SirenRepresentation sirena){...};
  public void IsUserAllowedToCreateSirena(bool isAllowed){...};
  public void IsTitleValid(bool isValid){...};
  public override SendMessage Build(){...};
}

Example of plan factory:

public class CreateSirenaPlanFactory : IFactory<IRequestContext,CommandPlan>
{
  private readonly Container container;
  private readonly IFactory<IRequestContext, CreateMessageBuilder> messageBuilderFactory;
  private readonly IFactory<CreateMessageBuilder, CreateSirenaStep.Buffer> bufferFactory;

  public CreateSirenaPlanFactory(Container container
  , IFactory<IRequestContext, CreateMessageBuilder> messageBuilderFactory
  , IFactory<CreateMessageBuilder,CreateSirenaStep.Buffer>  bufferFactory)
  
  {
    this.container = container;
    this.messageBuilderFactory = messageBuilderFactory;
    this.bufferFactory = bufferFactory;
  }

  public IPlan Create(IRequestContext context)
  {
    CreateMessageBuilder messageBuilder = messageBuilderFactory.Create(context);
    CreateSirenaStep.Buffer buffer = bufferFactory.Create(messageBuilder);

//Same buffer instance has to be shared between group of steps below
//But for each new request a new instance of plan and of buffer has to be created
    var validation = new CompositeCommandStep([
      container.GetInstance<CheckAbilityToCreateSirenaStep>(),
      container.GetInstance<ValidateTitleCreateSirenaStep>()
    ]);
    
    IStep<IRequestContext,CommandStep.Report>[] steps = [
      container.GetInstance<GetUserCreateSirenaStep>(),
      validation,
      container.GetInstance<RequestDBToCreateSirenaStep>(),
    ];
    return new CommandPlan(CreateSirenaCommand.NAME,steps);
  }
}

Question

How to bind this? I’m not eager to create factory for each IStep implementation that depends on 1 and more parameters, that being produced during a runtime. And I don’t know how to bind the buffer in this situation at all since SimpleInjector doesn’t have context.

P.S.
When I worked with Unity engine and with Zenject/Extenject there were much more options to divide contexts of a bindings and to create conditional bindings for an instances from certain factory. It’s a pity that SimpleInjector has a lack of such tools.
Because for each plan instance I could create context. And there would be 1 buffer instance created for each context. Furthermore I don’t need to create factory for each instance which need paramteres, because I could just bind native factory with parameters. It was a huge wonder for me when I found out that documentation doesn’t provide information about context, only about scopes. But I can’t create buffer instance in scope, because the scope will be closed just when Create method will finish it work, and the instance would be disposed as I understood from the documentation. Perhaps I can use Flowing scope, however I still don’t understand what is the way to resolve instance with parameter(s).

5

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật