user3354801
user3354801

Reputation: 23

Passing parameter to the constructor of a generic Class type

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

Answers (3)

Anand
Anand

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

Dirk
Dirk

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

stevethethread
stevethethread

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

Related Questions