如何使用Unity映射泛型类型?

Shu*_*kEv 2 .net c# dependency-injection ioc-container unity-container

我正在尝试使用Unity Configuration向类属性添加依赖项,并且我尝试注入的类型也是通用的.

我有界面

public interface ISendMessage
{
    void Send(string contact, string message);
}
Run Code Online (Sandbox Code Playgroud)

public class EmailService : ISendMessage
{
    public void Send(string contact, string message)
    {
        // do
    }
}
Run Code Online (Sandbox Code Playgroud)

public class MessageService<T> where T : ISendMessage
{          
}
Run Code Online (Sandbox Code Playgroud)

我尝试通过构造函数注入在其他类中使用它

public MyService(MessageService<ISendMessage> messageService)
{
}
Run Code Online (Sandbox Code Playgroud)

我怎么注射MessageService<EmailService>而不是MessageService<ISendMessage>

我试着通过app.config来做

<alias alias="MessageService'1" type="MyNamespace.MessageService'1, MyAssembly" />
    <alias alias="EmailMessageService'1" type="MyNamespace.MessageService'1[[MyNamespace.EmailService, MyAssembly]], MyAssembly" />
Run Code Online (Sandbox Code Playgroud)

我收到错误

无法解析类型名称或别名MessageService'1.请检查配置文件并验证此类型名称.

我如何通过MessageService<T>实现参数MessageService<EmailService>

谢谢

更新

我将我的课修改为以下内容:

public class MessageService<T> where T : ISendMessage
    {
        private T service;

        [Dependency]
        public T Service
        {
            get { return service; }
            set { service = value; }
        }
}
Run Code Online (Sandbox Code Playgroud)

并使用配置

<alias alias="ISendMessage" type="MyNamespace.ISendMessage, MyAssembly" />
    <alias alias="EmailService" type="MyNamespace.EmailService, MyAssembly" />

<register type="ISendMessage" mapTo="EmailService">
        </register>
Run Code Online (Sandbox Code Playgroud)

有用 :-)

Ste*_*ven 6

你不能简单地把一个转换MessageService<ISendMessage>成一个MessageService<EmailService>.为此,您需要MessageService<T>变体.仅支持接口(和委托)的差异.这不是Unity的事情,这是.NET框架的"限制"(以及自4.0以来的C#支持).所以你需要实现以下接口:

// note the 'out' keyword!!
public interface IMessageService<out T> 
    where T : ISendMessage
{
    T GetSendMessage();
}
Run Code Online (Sandbox Code Playgroud)

MessageService<T>班将不得不实现这个接口.但即使使用此代码,Unity也不会自动注入此代码.您必须在两种类型之间进行映射.例如,这是一个可能的注册:

container.Register<MessageService<ISendMessage>>(
    new InjectionFactory(c =>
        c.Resolve<MessageService<EmailService>>())); 
Run Code Online (Sandbox Code Playgroud)

请注意,我使用基于代码的配置.尽可能地防止使用基于XML的配置,因为XML配置很脆弱,容易出错,功能不强,难以维护.只注册在部署期间或之后实际需要的类型(并且个人,即使这样我也不会使用DI容器的XML API).