通用的类别限制

时间:2011-12-07 10:41:32

标签: c# generics inheritance

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

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

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

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

1 个答案:

答案 0 :(得分: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
{

}

[编辑]当您编辑问题时,您无法更改类以实现接口,这里有一些替代方案,但没有一个依赖于通用约束:

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

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

       public class SomeClass<T>{
          [ContractInvariantMethod]
          private void THaveUserID()
          {
              Contract.Invariant(typeof(T).GetProperty("UserId") != null);
          }
      }
      
      1. 使用部分类扩展现有类
      2. 如果生成了源类,则可以作弊。我使用这种技术,许多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
        {
        }
        

        这种方法效果很好,但只有在因为部分关键字技巧而可以在同一个项目中扩展类时才适用。