public class Factor1(int FactorX, int FactorY) : IFactors;
public class Factor2(int FactorX, int FactorY, int FZ) : IFactors;
public interface IFactors
{
int FactorX { get; set; }
int FactorY { get; set; }
}
public class BusinessLayerClass1
{
IFactors _factorObj;
public BusinessLayerClass1(IFactors factorObj)
{
_factorObj = factorObj;
}
public void Call() =>
new BusinessLayerClass2(_factorObj).ShowFactors();
}
public class BusinessLayerClass2
{
IFactors _factorObj;
public BusinessLayerClass2(IFactors factorObj)
{
_factorObj = factorObj;
}
public void ShowFactors()
{
Debug.WriteLine(String.Concat(_factorObj.FactorX.ToString(), " - " +
_factorObj.FactorY.ToString()));
}
}
Main program
using SimpleInjector;
class Program
{
public static void Main(string[] args)
{
List<Task> tasks = new List<Task>();
for (var i = 0; i < 10; i++)
{
tasks.Add(Task.Factory.StartNew((num) =>
{
int num_ = (int)num;
var factorObj = new Factor1() { FactorX = num_, FactorY = num_ + 1 };
var container = new Container();
var lifestyle = Lifestyle.Transient;
container.Register<BusinessLayerClass1>(lifestyle);
container.Register<BusinessLayerClass2>(lifestyle);
container.RegisterInstance<IFactors>(factorObj);
container.Verify();
var BL = container.GetInstance<BusinessLayerClass1>();
BL.Call();
}, i));
}
Task.WaitAll(tasks.ToArray());
}
}
Factor
classes consist of runtime data and you are injecting runtime data into your application components. This practice is discourages, as I explained here. The refernced article also explains what yo do instead, which is to "let runtime data flow through the method calls of constructed object graphs.".BL.Call
method to include that runtime data as input parameter, and later on call BL.Call(factorObj)
orIFactorContext
interface/class pair, register it as Scoped
, and supply the runtime values to a resolved IFactorContext
.Concerning the second option, this might look like this:
// Definitions
public interface IFactorContext { IFactors Factors { get; } }
public class FactorContext : IFactorContext { public IFactors Factors { get; set; } }
// Register container once
var container = new Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
container.Register<BusinessLayerClass1>();
container.Register<BusinessLayerClass2>();
container.Register<FactorContext>(Lifestyle.Scoped);
container.Register<IFactorContext, FactorContext>(Lifestyle.Scoped);
container.Verify();
// Operate loop many times
tasks.Add(Task.Factory.StartNew((num) =>
{
using (AsyncScopedLifestyle.BeginScope(container))
{
int num_ = (int)num;
var factorObj = new Factor1() { FactorX = num_, FactorY = num_ + 1 };
// Always reuse the single container instance here.
container.GetInstance<FactorContext>().Factor = factorObj;
var BL = container.GetInstance<BusinessLayerClass1>();
BL.Call();
}
}, i));