将参数传递给泛型类类型的构造函数

时间:2014-02-26 08:22:46

标签: c# generics

我已编写如下代码

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);
    }
}

我需要将参数传递给TPresenter和TForm。我可以这样做吗?如果是,如何实现这一目标?

3 个答案:

答案 0 :(得分:2)

简短的回答是,你不能只用通用约束来做到这一点。 C#语言中没有通用的constaint表示“类型必须有一个参数类型为X的构造函数”。

这意味着您无法使用TForm创建new TForm(presenter)类的对象。

但是 - 这是个好消息 - 仍然可以使用反射:

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 });

答案 1 :(得分:0)

这里的问题是new()泛型约束只能确保类型具有默认的无参数构造函数。所以你的泛型类型不知道它们支持带参数的构造函数。

您可以确保您的类型实现了一个允许您调用属性或方法的接口,而不是传递构造函数参数。 Init(xxx),允许您在构造后传递初始参数。例如,您可以使用名为IInitialisable的参数。然后,对类型进行类型约束。

答案 2 :(得分:0)

对于TPresenter和TForm,您可以替换TPresenter:class,new()与actulal实现或抽象类,其中包含参数化构造函数,如下所示

     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)
        {
        }
    }