是否可以在 C# 中创建通用限制,使用 where 来仅选择具有某些名称的字段的类。
例如,我有 AbstractService<T>
我有一个方法 IEnumerable<T> ProvideData(userId)
;
在里面提供数据我应该只选择具有相同用户 bla-bla-bla.Where(d => d.UserId == userId) 的实例。但无法解析 d.UserId。如何解决这个问题?
重要提示:我无法从具有 UserID 字段的类或接口(interface)继承 T。
界面就是您正在寻找的:
public interface IWithSomeField
{
int UserId { get; set; }
}
public class SomeGenericClasss<T>
: where T : IWithSomeField
{
}
public class ClassA : IWithSomeField // Can be used in SomeGenericClass
{
int UserId { get; set; }
}
public class ClassB // Can't be used in SomeGenericClass
{
}
[编辑] 当您编辑您的问题以声明您不能更改类来实现接口(interface)时,这里有一些替代方案,但没有一个依赖于通用约束:
- 检查构造函数中的类型:
代码:
public class SomeClass<T>{
public SomeClass<T>()
{
var tType = typeof(T);
if(tType.GetProperty("UserId") == null) throw new InvalidOperationException();
}
}
- 使用代码契约不变(不确定语法):
代码:
public class SomeClass<T>{
[ContractInvariantMethod]
private void THaveUserID()
{
Contract.Invariant(typeof(T).GetProperty("UserId") != null);
}
}
- 使用部分类扩展现有类
如果你的源类是生成的,你可以作弊。我将这种技术用于许多具有相同类型参数对象的 Web 引用
想象一下 Web 引用产生了这个代理代码:
namespace WebServiceA {
public class ClassA {
public int UserId { get; set; }
}
}
namespace WebServiceB {
public partial class ClassB {
public int UserId { get; set; }
}
}
您可以使用自己的代码包装它们:
public interface IWithUserId
{
public int UserId { get; set; }
}
public partial class ClassA : IWithUserId
{
}
public partial class ClassB : IWithUserId
{
}
然后,对于您的服务,您可以为多个 Web 服务的类中的任何一个实例化 AbstractService:
public class AbstractService<T> where T : IWithUserId
{
}
此技术非常有效,但仅适用于由于 partial 关键字技巧而可以在同一项目中扩展类的情况。
我是一名优秀的程序员,十分优秀!