Geo*_*ett 9 c# generics type-inference
我有一个具有此成员的接口(由存储库使用):
T FindById<T, TId>(TId id)
where T : class, IEntity<TId>
where TId : IEquatable<TId>;
Run Code Online (Sandbox Code Playgroud)
这允许调用者指定实体类型(T)及其Id字段类型(TId).然后,此接口的实现者将查找类型的实体,T并使用该id参数根据其id(已定义IEntity<TId>)对其进行过滤.
目前我这样称呼它:
int id = 123;
var myApproval = PartsDC.FindById<Approval, int>(id);
Run Code Online (Sandbox Code Playgroud)
理想情况下我想这样做:
int id = 123;
var myApproval = PartsDC.FindById<Approval>(id);
Run Code Online (Sandbox Code Playgroud)
我已经阅读了这个问题的答案:
我知道我不能得到我想要的语法,但可以接近.由于我的通用参数约束,我无法在我的情况下完全设置它.
这是我到目前为止所拥有的:
public class FindIdWrapper<T> where T : class
{
public readonly IDataContext InvokeOn;
public FindIdWrapper(IDataContext invokeOn)
{
InvokeOn = invokeOn;
}
T ById<TId>(TId id) where TId : IEquatable<TId>
{
return InvokeOn.FindById<T, TId>(id);
}
}
public static class DataContextExtensions
{
public static FindIdWrapper<T> Find<T>(this IDataContext dataContext) where T : class, IEntity
{
return new FindIdWrapper<T>(dataContext);
}
}
Run Code Online (Sandbox Code Playgroud)
我得到的编译错误是:
The type 'T' cannot be used as type parameter 'T' in the generic type or method 'PartsLegislation.Repository.IDataContext.FindById<T,TId>(TId)'. There is no implicit reference conversion from 'T' to 'PartsLegislation.Repository.IEntity<TId>'.
我理解它的含义是因为T我的包装器类只被限制为一个引用类型,但FindById函数想要它IEntity<TId>,但是我不能这样做,因为TId它在方法中(否则我回到正方形) ).
我怎样才能解决这个问题(或者我不能)?
这不能用通常的方法解决,因为您不能在TId事后说服编译器约束。但是,您可以颠倒顺序,即
var obj = ById(id).Find<SomeType>();
Run Code Online (Sandbox Code Playgroud)
虽然不那么优雅,但是可以。实现方式:
public Finder<TId> ById<TId>(TId id) where TId : IEquatable<TId>
{
return new Finder<TId>(this, id);
}
public struct Finder<TId> where TId : IEquatable<TId>
{
private readonly YourParent parent;
private readonly TId id;
internal Finder(YourParent parent, TId id)
{
this.id = id;
this.parent = parent;
}
public T Find<T>() where T : class, IEntity<TId>
{
return parent.FindById<T, TId>(id);
}
}
Run Code Online (Sandbox Code Playgroud)
警告:仅将两种参数类型明确地告诉它可能更容易。