2015-11-08 2 views
1

у меня есть базовый универсальный класс, который выглядит примерно так:Наследование и расширение ограничений в дженериков

public abstract class BaseTestDataEntity<T> 
     where T : IIdEntity, ICodeEntity, IActiveEntity, new() 
    { 
} 

Эти интерфейсы представляют собой поля в entities.This данных очень полезно, потому что с помощью этих интерфейсов можно написать общие базовые классы который может иметь такие методы, как «Добавить», «Обновить» и т. д.

Но что действительно полезно, это полная поддержка времени разработки, основанная на контрактах на интерфейсах.

Пример экземпляра:

public class Customer : BaseTestDataEntity<Customer> 
    {} 

Теперь у меня есть ситуация, в которой я хотел бы создать производный класс BaseTestDataEntity, который будет включать в себя все ограничения базы (так в коде, T должен иметь идентификатор, код и активный флаг)

Однако в производном классе я хочу добавить дополнительные ограничения.

Таким образом, мне не нужно дублировать конкретные методы в BaseTestDataEntity.

То, что я пытался и то, что я хочу сделать:

public class BaseTestDataEntityImpl<T> 
    : BaseTestDataEntity<T> where T : IIdEntity, ICodeEntity, IMultiTextEntity, IActiveEntity, new() 

    { 
     // This should enforce T constaints in the base class, but where do I put in new constraints in the derived T? 
    } 

ответ

2

Я не уверен, что вы на самом деле пытаетесь достичь, но в коде, все ограничения влияют только полученные BaseTestDataEntityImpl<T>. Они не передаются по цепочке наследования до BaseTestDataEntity.

Чтобы сделать это немного более ясным, давайте предположим, что у меня есть следующий класс:

public class FooHandler<T> where T : IFoo {} 

и теперь я хочу, чтобы иметь еще один класс, который наследуется FooHandler, но и требует это общий аргумент для реализации IBar.

public class FooAndBarHandler<TFooAndBar> where TFooAndBar : IFoo, IBar 

Как вы видите, я даже назвал общий параметр по-разному, потому что они на самом деле разные. TFooAndBar и это ограничение не имеет ничего общего с TFoo от класса FooAndBarHandler происходит от. Вы должны убедиться, что все, что вы переходите на FooHandler, реализует IFoo, и именно поэтому в этом случае TFooAndBar должен реализовать TFoo. Но есть и другие способы полного заполнения этого базового класса. Если предположить следующую ситуацию:

interface IFoo {} 
interface IBar : IFoo {} 

вы смогли бы просто написать

public class BarHandler<TBar> : FooHandler<TBar> where TBar : IBar 

потому TBar : IBar ограничение уже заставляет TBar также осуществлять IFoo.

Или вы могли бы жёстко FooHandler<MyFooImplementation>:

public class BarHandler<TBar> : FooHandler<MyFooImplementation> where TBar : IBar 
Смежные вопросы