简体   繁体   中英

Unity and using Generics to register interface

I have an interface

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

I want to be able to pass in an entity and have it return a Form object from the Build method ( Form object is not a Windows Form object it is my own class)

It seems to register fine using the code

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

I inject the IFormBuilder into the constructor of a FormProcessingService

private readonly IFormBuilder<applicationEntity, Form> _formBuilder;

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

The problem is in declaring the FormBuilder class

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

The error message I get is

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'.

Can anybody explain what is happening here?

In your interface definition you have these generic type constraints:

where T : Entity where K : Form

When you implement the interface, these type constraints are not inherited automatically, so you need to declare them on your class as well:

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

This tells compiler, that the generic type constraints on class FormBuilder are compatible with the ones from IFormBuilder and they can be used together.

Even if matching constraints are use there is still one issue in your method declaration:

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

Compiler complains here that there is no implicit conversion from Form to K . In order to fix that, there are 2 approaches you can take.

First approach is to convert Form to K , like this:

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

Second approach can be used if your class FormBuilder has a constructor with no parameters. In this case you can add constraint new() to your class declaration and then you can create new form using 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();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM