[英]Generic interface implementation: Generic return type and generic input type
我想創建類系統來概括從某些數據源獲取和發布數據。 我有兩種方法:GetData和PostData。 兩種方法都應具有某種輸入,GetData也應具有返回類型。 我試圖編寫通用接口並在“ DatabaseSource”類中實現它:
public class QueryParameter
{
public QueryParameter()
{
this.Direction = ParameterDirection.Input;
}
public string Name { get; set; }
public object Value { get; set; }
public ParameterDirection Direction { get; set; }
}
public class InputBase
{
public InputBase()
{
ResultMapping = new Dictionary<string, string>();
Parameters = new List<QueryParameter>();
}
public Dictionary<string, string> ResultMapping { get; set; }
public List<QueryParameter> Parameters { get; set; }
}
public class DatabaseInput: InputBase
{
public string Query { get; set; }
public DatabaseCommandType CommandType { get; set; }
}
public interface IDataSource<I> where I: InputBase
{
IEnumerable<T> GetData<T>(I input);
void PostData(I Input);
}
現在我試圖實現這樣的接口:
public class DatabaseDataSource: IDataSource<DatabaseInput>
{
public IEnumerable<T> GetData<T>(DatabaseInput Input)
{
//implementation
}
public void PostData(DatabaseInput Input)
{
//implementation
}
}
但是當我嘗試實例化數據源時,我遇到了一個問題:
IDataSource<InputBase> dataSource = new DatabaseDataSource();
我無法使用DatabaseInput,因為此代碼采用某種工廠方法,因此我應該能夠實例化其他IDataSource實現。
簡而言之,我想將Input和Output作為通用類型,並限制Input以匹配具體的IDataSource實現。
如果我正確理解了這一點(對我來說,這並不是100%清楚的事情),則您的數據源需要同時定義輸入和輸出。 如果您這樣做:
public IEnumerable<T> GetData<T>(DatabaseInput Input)
然后,該方法的實際實現可能會根據T
是什么而有很大的不同。 您不希望使用這種方法來檢查T
的類型並相應地分支代碼。
也許您想要的是這樣的:
public interface IDataSource<TInput, TOutput> where TInput: InputBase
{
IEnumerable<TOutput> GetData(TOutput input);
void PostData(TInput Input);
}
但是即使那樣,您仍然具有定義兩個看似無關的操作的接口。 ( TInput
不太可能既可以用作查詢檢索數據,也可以用作發布/修改數據的命令。)
因此,也許您可以將其進一步分解:
public interface IDataSource<TInput, TOutput> where TInput: InputBase
{
IEnumerable<TOutput> GetData(TOutput input);
}
public interface IDataCommand<TInput> where TInput:InputBase
{
void PostData(TInput Input);
}
要實例化它,您可以使用抽象工廠:
public interface IDataSourceFactory<TInput, TOutput>
{
IDataSource<TInput, TOutput> Create();
void Release(IDataSource<TInput, TOutput> created);
}
這樣做的原因是因為它避免了類調用var dataSource = new [whatever].
如果這樣做,那么它一定會破壞實現接口的目的。 無論您實現哪種接口,只要您顯式調用new
並創建特定類型,您的類都將與該類型 (而不是接口)耦合。
這解決了最初的問題。 抽象工廠的實現是什么? 好消息是,依賴於工廠的類並不關心工廠的實現是什么。 但是您仍然需要一個。 一種解決方法是使用DI容器。 溫莎很有用,因為它提供了創建抽象工廠的模式。 這篇博客文章更詳細地描述了如何做到這一點。
您可以使用where約束,請單擊此處以獲取有關約束的更多信息。
where T : class //The type argument must be a reference type; this applies also to any class, interface, delegate, or array type.
where T : <interface name> //The type argument must be or implement the specified interface. Multiple interface constraints can be specified. The constraining interface can also be generic.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.