これは共分散と反分散に関係しています。
あなたの質問では、次のことを述べました。
... GenericQueryRepository は IGenericQueryRepository を実装し、Client は IClient を実装します。
フルーツを使って簡単にしましょう: Fruit は IFruit を実装します。Tree クラスも作成します。
public interface IFruit { }
public class Fruit : IFruit { }
public class Tree<T> where T : IFruit { }
Tree<IFruit> tree = new Tree<Fruit>() // error
これにより、発生しているのと同じ種類のエラーが再現されます。なんで?単純。
Fruit は IFruit を実装していますが、Fruit Tree は IFruit ツリーを実装していません。当然のことですが、Fruit Tree と IFruit Tree の間でキャストを行うことはできません。どちらもツリーですが、型パラメーターが異なります。それらの型パラメーターが互いに関連しているという事実は重要ではありません。
つまり、型パラメーターが一致しないため、フルーツ ツリーと IFruit ツリーの間で可能なキャストはありません。
一般に、ジェネリックでキャストするときは、それらの型パラメーターが一致していることを確認してください。ただし、いくつかの例外的なケースがあります。ジェネリック インターフェイスの差異を参照してください。
あなたの場合、 IClient を GenericQueryRepository クラスの型パラメーターとして使用することで修正できます。これを行うと、型パラメーターが一致するため、キャストが可能になります。しかし、私はあなたのアプリケーション アーキテクチャを知らないので、この修正はあなたの場合には当てはまらないかもしれません。
編集:理解しやすくするために、以下のコードをコピーして貼り付け、コンパイラの内容を確認してください。
interface IFruit { }
class Fruit : IFruit { }
interface ITree<T> where T : IFruit { }
class Tree<T> : ITree<T> where T : IFruit { }
class Program
{
static void Main(string[] args)
{
ITree<Fruit> test1 = new Tree<Fruit>(); // compiles: type parameters match
ITree<IFruit> test2 = new Tree<Fruit>(); // fails: type parameters don't match
ITree<Fruit> test3 = new Tree<IFruit>(); // fails: type parameters don't match
ITree<IFruit> test4 = new Tree<IFruit>(); // compiles: type parameters match
IEnumerable<IFruit> test5 = new List<Fruit>(); // compiles: this is one of the exceptional cases
}
}
これにより、何が可能で何が不可能かが明確になるはずです。