开发者

Return list of generic implementations possible

开发者 https://www.devze.com 2023-03-11 23:04 出处:网络
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:

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 TModels.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号