通用类型,接口

本文关键字:接口 类型 | 更新日期: 2023-09-27 18:22:05

我想创建一个通用通知引擎。这个想法是用一个单一的核心引擎来处理任何类型的通知。该引擎将处理通知并处理所有日志记录、错误处理等

我创建了3个简单的接口:

public interface INotificationInput
{
    /// <summary>
    /// Friendly Name for logging/tracing usage
    /// </summary>
    string FriendlyName { get; set; }
    string NotificationCode{ get; set; }
    Double Version { get; set; } 
}
public  interface INotificationOutput
{
    /// <summary>
    /// Friendly Name for logging/tracing usage
    /// </summary>
    string FriendlyName { get; }
}
public interface INotificationProvider<out Toutput, Tinput> where Toutput : INotificationOutput where Tinput : INotificationInput
{
    /// <summary>
    /// Friendly Name for logging/tracing usage
    /// </summary>
    string FriendlyName { get; set; }
    /// <summary>
    /// Generates and returns an INotificationOutput from data
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    Toutput GenerateNotificationOutput(Tinput data);
}

因此,INotificationProvider将阻塞INotificationInput以创建INotificationOutput。

这可能是发送电子邮件、短信的信息,你能想到的,引擎会调用方法,并进行调度、记录、处理错误等魔术

我实现了这样的接口:

/// <summary>
    /// INotificationInput represented by a dummy object
    /// </summary>
    public class DummyNotificationInput : INotificationInput
    {
        public string FriendlyName { get; set; }
        public string NotificationCode { get; set; }
        public double Version { get; set; }
    }
public class DummyNotificationOutput : INotificationOutput
{
    public string FriendlyName { get; private set; }
}
public class DummyProvider : INotificationProvider<DummyNotificationOutput, DummyNotificationInput>
{
    public string FriendlyName { get; set; }
    public DummyNotificationOutput GenerateNotificationOutput(DummyNotificationInput data)
    {
        throw new NotImplementedException();
    }
}

现在我希望我的引擎有一个供应商列表:

 var providersList = new List<INotificationProvider<INotificationOutput, INotificationInput>>();

问题是我不能去以下地方:

providersList.Add(new DummyProvider<DummyNotificationOutput, DummyNotificationInput>());

必须有一个解决方案。我用错方法了吗?

通用类型,接口

INotificationProvider的第二个泛型类型参数不是协变的(在概念级别上),但您试图将其当作协变来使用。它实际上是相反的。

INotificationProvider对象列表中,您已将输入通知定义为INotificationInput。这意味着添加到此列表的对象需要能够接受任何类型的INotificationInput作为其GenerateNotificationOutput函数的输入。您正在尝试添加一个只知道如何处理DummyNotificationInput对象的对象。如果传递其他类型的输入,它就会失败。

如果您希望能够将INotificationInput对象添加到该列表中,则您的提供者需要接受该对象,或者该列表需要将所有对象定义为接受DummyNotificationInput

正如Servy已经回答的那样,由于providersList所期望的,您无法真正做到这一点

考虑到这一点,实际上可能更简单的做法是使INotificationProvider非通用:

public interface INotificationProvider
{
    /// <summary>
    /// Friendly Name for logging/tracing usage
    /// </summary>
    string FriendlyName { get; set; }
    /// <summary>
    /// Generates and returns an INotificationOutput from data
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    INotificationOutput GenerateNotificationOutput(INotificationInput data);
}

然后DummyProvider变为:

public class DummyProvider : INotificationProvider
{
    public string FriendlyName { get; set; }
    public INotificationOutput GenerateNotificationOutput(INotificationInput data)
    {
        throw new NotImplementedException();
    }
}

现在,可能不是您想的那样——您希望将DummyNotificationInput实例传递给DummyProvider

你可以在你的Provider代码中键入check

public class DummyProvider : INotificationProvider
{
    public string FriendlyName { get; set; }
    public INotificationOutput GenerateNotificationOutput(INotificationInput data)
    {
        if (!(data is DummyNotificationInput)) throw new ArgumentException("Invalid type specified", "data");
        return something...;
    }
}

显然,您会失去设计时检查,但如果您真的需要将它们放在协变列表中,则无法提供具有派生泛型类型参数

的实现器