类字段限制的泛型

本文关键字:泛型 字段 | 更新日期: 2023-09-27 18:17:06

是否有可能在c#中创建通用限制,使用只选择具有某些名称的字段的类?

例如

,我有AbstractService<T>我有一个方法IEnumerable<T> ProvideData(userId);

在提供数据中,我应该只选择具有相同用户的实例等等等等。其中(d => d. userId == userId)。但是d.UserId无法解析。如何解决这个问题?

重要:我不能从类或接口继承T,它们有UserID字段

类字段限制的泛型

你正在寻找的是一个接口:

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
{
}

[Edit]当你编辑你的问题时,你不能改变类来实现一个接口,这里有一些替代方案,但没有一个依赖于泛型约束:

  1. 检查构造函数中的类型:
代码:

public class SomeClass<T>{
    public SomeClass<T>()
    {
        var tType = typeof(T);
        if(tType.GetProperty("UserId") == null) throw new InvalidOperationException();
    }
}
  1. 使用代码契约不变量(不确定语法):
代码:

 public class SomeClass<T>{
    [ContractInvariantMethod]
    private void THaveUserID()
    {
        Contract.Invariant(typeof(T).GetProperty("UserId") != null);
    }
}
  1. 用部分类扩展现有类

如果生成了源类,可以作弊。我对许多具有相同类型参数对象的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
{
}

这项技术非常有效,但仅适用于由于部分关键字技巧而可以在同一项目中扩展class的情况。