Skip to main content
deleted 10 characters in body
Source Link
John Wu
  • 27k
  • 10
  • 69
  • 93
class QuotePipelineFactory : IQuotePipelineFactory { protected readonly IUnityContainer _container; public QuotePipelineFactory(IUnityContainer container) { _container = container; } public QuotePipeline GetPipeline() { var p = new List<Func<Quote,Quote>>QuotePipeline(); var d1 = _container.Resolve<Service_1>(); p.Add( q => d1.DoSomething_1(q) ); var d2 = _container.Resolve<Service_2>(); p.Add( q => d2.DoSomething_2(q) ); return p; } } 
class QuotePipelineFactory : IQuotePipelineFactory { protected readonly IUnityContainer _container; public QuotePipelineFactory(IUnityContainer container) { _container = container; } public QuotePipeline GetPipeline() { var p = new List<Func<Quote,Quote>>(); var d1 = _container.Resolve<Service_1>(); p.Add( q => d1.DoSomething_1(q) ); var d2 = _container.Resolve<Service_2>(); p.Add( q => d2.DoSomething_2(q) ); return p; } } 
class QuotePipelineFactory : IQuotePipelineFactory { protected readonly IUnityContainer _container; public QuotePipelineFactory(IUnityContainer container) { _container = container; } public QuotePipeline GetPipeline() { var p = new QuotePipeline(); var d1 = _container.Resolve<Service_1>(); p.Add( q => d1.DoSomething_1(q) ); var d2 = _container.Resolve<Service_2>(); p.Add( q => d2.DoSomething_2(q) ); return p; } } 
added 2 characters in body
Source Link
John Wu
  • 27k
  • 10
  • 69
  • 93

NOwNow write a factory. Unity will always inject itself automatically if your class has IUnityContainer as a constructor argument.

If your quote pipelines are always the same, you can of course store it as a single instance within the factory, which will be appropriateappropriately lifetime-scoped by Unity.

If the pipelines differ, you can always supplyadd input arguments to the factoryGetPipeline() and then possibly use a strategy patternstrategy pattern to pick and choose which processors to include in the pipeline.

NOw write a factory. Unity will always inject itself automatically if your class has IUnityContainer as a constructor argument.

If your quote pipelines are always the same, you can of course store it as a single instance within the factory, which will be appropriate lifetime-scoped by Unity.

If the pipelines differ, you can always supply input arguments to the factory and then use a strategy pattern to pick and choose which processors to include in the pipeline.

Now write a factory. Unity will always inject itself automatically if your class has IUnityContainer as a constructor argument.

If your quote pipelines are always the same, you can of course store it as a single instance within the factory, which will be appropriately lifetime-scoped by Unity.

If the pipelines differ, you can always add input arguments to GetPipeline() and then possibly use a strategy pattern to pick and choose which processors to include in the pipeline.

Source Link
John Wu
  • 27k
  • 10
  • 69
  • 93

This piece of code caught my attention:

public override List<Func<Quote, Quote>> QuotePipeline => new List<Func<Quote, Quote>> { Service_1.DoSomething_1, // ... Service_N.DoSomething_N }; 

The fact that you're taking a list of discrete elements and immediately putting them in a list suggests that there is an implicit business concept here that isn't embodied in a class. If it were me, I'd have a class to represent the pipline and inject either the pipeline itself or a factory that will allow the caller to create one.

If you're writing a factory, it is "OK" to pass in the Unity Container itself, since dependency and lifespan management is part of a factory's single responsibility. This way you are getting the benefits of the service locator pattern without breaking the rules too badly for IoC.

When you need to unit test, you can just substitute a different pipeline factory that returns mocks.

So, first we define the pipeline:

public class QuotePipeline : List<Func<Quote,Quote>> { public Quote Execute(Quote quote) { foreach (var f in this) quote = f(quote); return quote; } } 

NOw write a factory. Unity will always inject itself automatically if your class has IUnityContainer as a constructor argument.

class QuotePipelineFactory : IQuotePipelineFactory { protected readonly IUnityContainer _container; public QuotePipelineFactory(IUnityContainer container) { _container = container; } public QuotePipeline GetPipeline() { var p = new List<Func<Quote,Quote>>(); var d1 = _container.Resolve<Service_1>(); p.Add( q => d1.DoSomething_1(q) ); var d2 = _container.Resolve<Service_2>(); p.Add( q => d2.DoSomething_2(q) ); return p; } } 

Then inject the factory and retrieve the pipeline itself:

public class QuoteCreateService : IQuoteProcessor { protected readonly IQuotePipelineFactory _quotePipelineFactory; public QuoteCreateService(IQuotePipelineFactory quotePipelineFactory) { _quotePipelineFactory = quotePipelineFactory; } public Quote CreateQuote(Quote quote) { var p = _quotePipelineFactory.GetPipeline(); return p.Execute(quote); } } 

Notice now there is only one dependency, and it can support any number of quote processors.

If your quote pipelines are always the same, you can of course store it as a single instance within the factory, which will be appropriate lifetime-scoped by Unity.

If the pipelines differ, you can always supply input arguments to the factory and then use a strategy pattern to pick and choose which processors to include in the pipeline.