2011-12-07 98 views
1

是否有可能在C#中使用何处仅选择具有某个名称的字段的类来创建通用限制。通用在哪里限制类字段

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

里面提供的数据我应该只选择具有相同用户bla-bla-bla.Where(d => d.UserId == userId)的实例。但d.UserId无法解决。如何解决这个问题?

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

回答

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. 入住构造类型:

代码:

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 
{ 

} 

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

public class AbstractService<T> where T : IWithUserId 
{ 
} 

这种技术效果很好,但只适用于由于部分关键字技巧而可以在同一个项目中扩展类的情况。

+0

+1,或从一个公共基类派生,可能是抽象的 – StuartLC

+0

你更新了你的问题,告诉继承一个接口是不可能的......让我试试另一个想法 –

+0

当从另一个类继承,或者实现一个接口不是允许的话,那恐怕是不可能的。 –