Unity 和使用泛型注册接口

Unity and using Generics to register interface

我有一个界面

public interface IFormBuilder<T,K> where T : Entity where K : Form
{
    K Build(T entity);
}

我希望能够传入一个实体并使其成为 return 来自 Build 方法的 Form 对象(Form 对象不是 Windows Form对象是我自己的class)

使用代码似乎可以正常注册

container.RegisterType(typeof(IDummyFormBuilder<,>), typeof(DummyFormBuilder<,>));

我将 IFormBuilder 注入到 FormProcessingService

的构造函数中
private readonly IFormBuilder<applicationEntity, Form> _formBuilder;

public FormProcessingService(IFormBuilder<applicationEntity, Form> formBuilder)
{            
    _formBuilder = formBuilder;
}

问题在于声明 FormBuilder class

public class FormBuilder<T, K> : IFormBuilder<T, K>
{
    public K Build(T entity)
    {
        return new Form();
    }
}

我得到的错误信息是

Error CS0314 The type 'T' cannot be used as type parameter 'T' in the generic type or method 'IFormBuilder'. There is no boxing conversion or type parameter conversion from 'T' to 'Entity'.

The type 'K' cannot be used as type parameter 'K' in the generic type or method 'IFormBuilder'. There is no boxing conversion or type parameter conversion from 'K' to 'SmartForm'.

谁能解释一下这里发生了什么?

在您的接口定义中,您有这些泛型类型约束:

where T : Entity where K : Form

当您实现接口时,这些类型约束不会自动继承,因此您还需要在您的 class 上声明它们:

public class FormBuilder<T, K> : IFormBuilder<T, K>
    where T : Entity where K : Form
{
    // your class code
}

这告诉编译器,class FormBuilder 上的泛型类型约束与 IFormBuilder 中的泛型约束兼容,它们可以一起使用。

即使使用了匹配约束,您的方法声明中仍然存在一个问题:

public K Build(T entity)
{
    return new Form();
}

编译器在这里抱怨没有从 FormK 的隐式转换。为了解决这个问题,您可以采用两种方法。

第一种方法是将 Form 转换为 K,像这样:

public K Build(T entity)
{
    return (K)(new Form());
}

如果您的 class FormBuilder 具有不带参数的构造函数,则可以使用第二种方法。在这种情况下,您可以将约束 new() 添加到 class 声明中,然后您可以使用 new K():

创建新表单
public class FormBuilder<T, K> : IFormBuilder<T, K>
where T : Entity where K : Form, new()
{
    public K Build(T entity)
    {
        return new K();
    }
}