Reputation: 23
I have written the code as below
public interface IScreenBuilder
{
void Build<TBusinessLogic, TPresenter, TForm> (ILog logger)
where TPresenter : class, new()
where TForm : class, new();
}
public class ScreenBuilder: IScreenBuilder
{
private ILog _logger;
public void Build<TBusinessLogic, TPresenter, TForm>(ILog logger)
where TPresenter : class, new()
where TForm : class, new()
{
_logger = logger;
TBusinessLogic businessLogic = new BusinessLogicBuilder().Build<TBusinessLogic>();
TPresenter presenter = new TPresenter(businessLogic);
TForm form = new TForm(presenter);
}
}
I need to pass a parameter to the TPresenter and TForm. Is it possible for me to do this? If yes how to achieve this?
Upvotes: 2
Views: 709
Reputation: 757
For TPresenter and TForm you can replace where TPresenter : class, new() with a actulal implementation or abstract class which contains parametrized constructor as below
public void Build<TBusinessLogic, TPresenter, TForm>(ILog logger)
where TPresenter : PresenterClass, new()
where TForm : FormClass, new()
{
_logger = logger;
TBusinessLogic businessLogic = new BusinessLogicBuilder().Build<TBusinessLogic>();
TPresenter presenter = new TPresenter(10);
TForm form = new TForm(20);
}
public abstract class PresenterClass
{
public PresenterClass(int parm)
{
}
}
public abstract class FormClass
{
public FormClass(int parm)
{
}
}
Upvotes: 0
Reputation: 10958
The short answer is that you can't do that with just generic constraints. There is no generic constaint in the C# language that says the "type must have a constructor with a parameter of type X".
That means you can't create an object of the TForm
class using new TForm(presenter)
.
But - and that's the good news - it is still possible to do using reflection:
var type = typeof(TPresenter);
var constructor = type.GetConstructors()
.FirstOrDefault(c =>
(c.GetParameters().Count() == 1) &&
(c.GetParameters()[0].ParameterType == typeof(TBusinessLogic)));
if (constructor == null)
{
throw new SomeException();
}
TPresenter presenter = (TPresenter)constructor.Invoke(
new object[]{ businessLogic });
Upvotes: 2
Reputation: 2524
The problem here is that the new() generic constraint only ensures that the types have a default parameterless constructor. So your generic types don't know that they support a constructor that takes parameters.
Rather than passing in constructor parameters, you could ensure your types implement an interface that allows you to call a property or method e.g. Init(xxx), that allows you to pass in initial parameters after construction. For example, you could could have a parameter called IInitialisable. Then you make that a type constraint on your types.
Upvotes: 0