I have the following interface:
public interface Query<TModel>
{
IList<TModel> GetData();
}
I would like to have some service that can return all the queries implementations:
public interface IQueryProvider
{
List<Query<>> GetAllQueries();
}
and then be able to call GetData on one:
var queries = provider.GetAllQueries();
var results = queries[0].GetData();
Would it be possible to achieve this with gen开发者_Python百科erics?
You can't use the open generic type Query<>
, except inside typeof()
. If you wanted to refer to a set of queries (type not specified) you would need a non-generic API, for example:
public interface IQuery {
IList GetData();
Type QueryType { get; }
}
public interface IQuery<TModel> : IQuery
{
new IList<TModel> GetData();
}
public interface IQueryProvider
{
List<IQuery> GetAllQueries();
}
this, however, means you need to provide a shadow implementation of IQuery
for each, which is a pain. Note there is also an ambiguity in the above if any service implements both IQuery<Foo>
and IQuery<Bar>
- in that there is no obvious way of indicating QueryType
.
If you throw out IList<>
and replace it with IEnumerable<>
you can make your interface covariant. Unfortunately there is no ReadOnlyList<>
or ReadOnlyCollection<>
interface(No idea what MS was thinking there).
public interface Query<out TModel>
{
IEnumerable<TModel> GetData();
}
public interface IQueryProvider
{
List<Query<object>> GetAllQueries();
}
Note that this will only work for reference type TModel
s.
Your IQueryProvider has to know what generic type IQuery is using. There are 2 solutions I can think of.
Solution 1: Define a generic type when you create the IQueryProvider instance
public interface IQueryProvider<TModel>
{
List<IQuery<TModel>> GetAllQueries();
}
Solution 2: Pass in the type in the method
public interface IQueryProvider
{
List<IQuery<TModel>> GetAllQueries<TModel>();
}
Also, I suggest you to change Query to IQuery for standard naming convention.
精彩评论