I assume that you have done the exercise Producer-Consumer using BlockingCollection.
In the original version Producers and Consumers could only use int's.
In this exercise you must make a new version of the Producer, Consumer, etc. so that they become generic - and will be able to handle any type (not just int).
Create a class Producer. The class must be generic (Producer<T>).
The class must use BlockingCollection as the type of the buffer to add to.
The Producer should do Console.WriteLine(...) every time an element has been added to the buffer.
The Producer probably uses an ordinary for loop, however the indexes from the for loop can not be used as a parameter to buffer.Add(...), which wants an object of type T (the generic type parameter).
Create an interface IElementFactory, and add an object of this type as a parameter to the Producers constructor.
Create a class Consumer. The class must be generic (Consumer<T>).
Create a class MiddleMan. The class must be generic (MiddleMan<T>).
The ordinary MiddleMan uses the same type <T> for the ingoing and the outgoing buffers.
Now you are going to make another (and more flexible) class MiddleMan2 which can use different (but related) types for the ingoing and the outgoing buffer.
Create a class MiddleMan2. The class must be generic: MiddleMan2<TIn, TOut> where TIn : TOut { ... }
Substitute all Console.WriteLine(...) with logging.