通用的类别限制

Ph0*_*n1x 1 c# generics inheritance

是否可以在C#中创建通用限制,使用where仅选择具有某个名称的Field的类.

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

在内部提供数据我应该只选择具有相同用户bla-bla-bla.Where的实例(d => d.UserId == userId).但是d.UserId无法解决.怎么可能解决这个问题?

重要提示:我无法从具有UserID字段的类或接口继承T.

Ste*_*e B 7

界面是您正在寻找的:

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
{

}
Run Code Online (Sandbox Code Playgroud)

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

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

代码:

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

代码:

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

如果生成了源类,则可以作弊.我使用这种技术,有许多Web引用具有相同类型的参数对象

想象一下,Web引用产生了这个代理代码:

namespace WebServiceA {

    public class ClassA {
        public int UserId { get; set; }
    }
}
namespace WebServiceB {

    public partial class ClassB {
        public int UserId { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以在自己的代码中使用它们来包装它们:

public interface IWithUserId
{
    public int UserId { get; set; }
}
public partial class ClassA : IWithUserId 
{

}
public partial class ClassB  : IWithUserId
{

}
Run Code Online (Sandbox Code Playgroud)

然后,对于您的服务,您可以为几个Web服务的任何类实例化AbstractService:

public class AbstractService<T> where T : IWithUserId
{
}
Run Code Online (Sandbox Code Playgroud)

这种技术很有效,但只有在因为partial关键字技巧而可以在同一个项目中扩展类时才适用.