[英]Generic types, Interfaces
我想創建一個通用的通知引擎。 這個想法是有一個單一的核心引擎來處理任何類型的通知。 該引擎將處理通知並處理所有日志記錄,錯誤處理等。
我創建了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...;
}
}
顯然,您浪費了設計時間檢查-但是,如果您確實需要將它們放在協變量列表中,則無法提供具有派生泛型類型參數的實現程序
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.