我一直在尝试让这个像静态扩展这样的东西工作一段时间:
public static class MixedRepositoryExtensions {
public static Task<TEntity> FindBySelectorAsync<TRepository, TEntity, TSelector>(
this TRepository repository,
TSelector selector)
where TRepository : IReadableRepository<TEntity>, IListableRepository<TEntity>
where TEntity : class, ISearchableEntity<TSelector>
=> repository.Entities.SingleOrDefaultAsync(x => x.Matches(selector));
}
然而,据我了解,C# 在设计上并未将通用约束作为其推理过程的一部分,导致在尝试调用它时出现以下 CS0411 错误:
无法从用法中推断出方法“MixedRepositoryExtensions.FindBySelectorAsync(TRepository, TSelector)”的类型参数。尝试明确指定类型参数。
示例调用方法(其中 ProjectRepository 扩展了 IReadableRepository<Project> 和 IListableRepository<Project> 并且 project 扩展了 ISearchableEntity<int>):
await (new ProjectRepository()).FindBySelectorAsync(0);
我考虑过在所有调用者上显式定义它们,但是,这种方法并不理想,因为它会在很多地方使用并且有很多长名称类型。
我还考虑过将两个接口继承为一个接口,如下所示:
IReadableAndListableRepository<TEntity> :
IReadableRepository<TEntity>,
IListableRepository<TEntity>
但是,由于我将不止使用一个扩展,而不仅仅是使用一个组合,我发现这会导致界面爆炸(如果是这样的话?)。例如,这将是另一个:
IUpdatableAndListableRepository<TEntity :
IUpdatableRepository<TEntity>,
IListableRepository<TEntity>
我在这里从 Eric Lippert 那里找到了一个提示,即使用 F# 可能会有所帮助(因为我已经绝望了):
泛型:为什么编译器不能在这种情况下推断类型参数?
我玩了一下 F#,但发现很少有关于将类型约束到多个接口(或与此相关的任何特定接口)的文档,并且无法克服一些错误。这是我最后一次尝试。我意识到该方法不会返回相同的值,我只是暂时尝试让约束很好地发挥作用。抱歉,如果做得不好,这是我第一次玩 F#。
[<Extension>]
type MixedRepositoryExtensions() =
[<Extension>]
static member inline FindBySelectorAsync<'TSelector, 'TEntity when 'TEntity: not struct and 'TEntity:> ISearchableEntity<'TSelector>>(repository: 'TRepository when 'TRepository:> IReadableRepository<'TEntity> and 'TRepository:> IListableRepository<'TEntity>, selector: 'TSelector) = repository;
但是,此实现会导致以下错误,均引用定义了 FindBySelectorAsync 的行:
守候你守候我
慕森王
相关分类