[英]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.