如何最好地限制Generic <t>类中的类型,其中所有类都派生自相同的基类

时间:2017-01-04 11:14:39

标签: c# generics dynamics-crm

我使用Dynamics CRM(这在技术上与此讨论无关,但解释了此问题的一些背景故事)。有许多类型都来自类Entity。我希望创建一个Class<T>() : where T: Entity,但有一个进一步的限制,它只对从Entity派生的特定类进行操作。

我目前执行此操作的方法是使enum与我要使用的实体名称匹配,if/else if/else匹配这些类型,throw如果传递了无效类型英寸

感觉很笨拙,我觉得写些东西会更好,

public class ProductConverter<t> where T: Entity (OpportunityProduct, QuoteProduct, AccountProduct) { ... }

这种类型引擎可以说,“我们正在处理实体的基类,而且我们只处理这些派生类型的实体”。

我希望这足以清楚地理解我在做什么 - 我的目的是创建一个能够处理实体记录之间转换的引擎,可以扩展而无需重新编写大块代码(实际上,添加映射和类型参数)。我确信有更好的方法可以做到这一点,所以如果你看到它们,请指出它们:)

edit @ henk-holterman问我是否可以改变课程。这是不可能的,因为它们是生成的类文件,用作Dynamics CRM Web服务的接口。

edit 正如@jamiec所指出的那样,类是partial,所以我可以通过在我想要修改的特定类上定义一个接口来实现这一点。

2 个答案:

答案 0 :(得分:4)

您的自动生成的类几乎肯定是partial,这意味着每个实现共享接口的文件都应该有一个单独的文件

 public partial class QuoteProduct : IProduct 
 { // probably empty }

然后您可以通过界面限制您的泛型类型:

public class ProductConverter<T> where T: Entity, IProduct 
{ // your implementation }

答案 1 :(得分:0)

您需要实现一个接口,然后从您要使用的每个类实现该接口。例如,这可能是这样的:

public interface IProduct
{
   int ProductId {get;set;}
}

public class ProductConverter<t> where T: Entity, IProduct
{
   //Do sth. with your ProductId
}

因为您的类是按照您在评论中描述的那样生成的,所以在您的特殊情况下这将不起作用。然后你只能使用类型检查:

T obj;
if (obj.GetType() == typeof(YourClass))

//OR

if (obj is YourClass)

问题是如果你做某事。就像你在你的问题中所期望的那样,你的变量是无用的,因为你不知道它是哪种类型。

 public void ProductConverter<t>(T obj) where T: Entity (OpportunityProduct, QuoteProduct)
 {
    obj. //What to do here?? It can hold Methods from both OpportunityProduct or QuoteProduct
 }

所以事实上你有可能概括你需要的东西或者做出类型检查。

如果您知道会发生什么,dynamic关键字可以为您提供帮助。在这种情况下,您不需要通用方法。例如,这可能如下所示:

public void ProductConverter(dynamic entity)
{
   //Make sure the method exists. Or you will get an Exception.
   //The compiler can't warn you about this
   entity.SomeMethod1();
   entity.SomeMethod2();
}

如果你想写一个转换器,不确定这是否真的可以帮到你。