Обеспечить определенный тип класса для интерфейса? - PullRequest
1 голос
/ 26 марта 2012

У меня есть несколько элементов управления в одном из моих приложений, которые, очевидно, расширяют класс Control.

Мне нужно несколько из них, чтобы иметь некоторый общий интерфейс, поэтому я создал интерфейс, который охватывает общую функциональность.

Можно ли каким-либо образом обеспечить, чтобы мой интерфейс передавался только подклассу Control?

т.е. (Pseudo)

interface IEmbed

class MyControl1 : Control, IEmbed

class MyControl2 : Control, IEmbed

class MyClass : IEmbed

В идеале я бы хотел, чтобы компилятор не работал здесь, потому что MyClass пытается реализовать IEmbed, даже если он не является элементом управления.

Я ошибся в этом или есть способ заставить это поведение?

Редактировать

Меня спросили, почему яЯ хочу применить это поведение.

У меня есть метод, который я хочу взять любую реализацию IEmbed и добавить его в качестве дочернего элемента управления в другой элемент.

Это все хорошо, но Controls.Add () отказывается принимать объект IEmbed, и это не компилируется.

Я подумал, если скажу компилятору, что что-либо реализующее IEmbedдолжен быть контроль, он может работать?

Ответы [ 6 ]

6 голосов
/ 26 марта 2012

Нет, нет способа принудительно применить это во время компиляции.

Вы могли бы принудительно применить его во время выполнения, проверив свой код структуры, если obj is Control перед использованием obj в качествеIEmbed экземпляр.

Обновление: Судя по отзывам из комментариев, похоже, что хорошим решением было бы унаследовать от промежуточного abstract class EmbedControl : Control и заставить ваш метод принять EmbedControl вместо IEmbed (в этом случае на самом деле не было бы необходимости сохранять интерфейс, поскольку вы можете просто использовать abstract методы в базовом классе).

Хотя вышеприведенное будет работать хорошопри некоторых обстоятельствах нежелательно заставлять разработчиков «клиентских» классов наследовать от вашего собственного промежуточного класса, даже если вам нужно, чтобы они наследовали от «базового» класса Control одновременно.В этом случае другим хорошим подходом будет использование обобщений:

public void DoSomethingWithControl<T>(T control) where T : Control, IEmbed
5 голосов
/ 26 марта 2012

Если вам нужно выполнить такую ​​проверку, я бы посоветовал вам пересмотреть свой дизайн. Интерфейс является просто контрактом и не накладывает ограничений на то, что может его придерживаться. Если тип важен, вы должны попробовать другой подход, например, базовый класс. Как насчет использования абстрактного класса (где вы можете указать ограничения типов), который требует наследника для реализации методов вашего интерфейса?

interface IInterface
{
    void Method1();
    int Property1 { get; }
}

abstract class BaseClass: Control, IInterface
{
    public abstract void Method1();
    public abstract int Property1 { get; }
}

Это будет гарантировать только то, что любой класс, производный от BaseClass, является одновременно элементом управления и реализует IInterface.

2 голосов
/ 26 марта 2012

Я не думаю, что есть способ обеспечить что-то подобное, но я не думаю, что вам действительно нужно, поскольку вы можете просто проверить во время выполнения, является ли экземпляр вашего интерфейса элементом управления.

НО: альтернативы просто используют абстрактный интерфейс (производный от Control) вместо интерфейса:

abstract class EmbedControl
   : Control
{
   // your abstract members
}

class MyControl1 : EmbedControl
0 голосов
/ 26 марта 2012

Ну, решение, которое я предоставляю, очень уродливо, но оно не работает во время компиляции.

public interface IEmbed<T> where T: Control
{
}

public class A :Control, IEmbed<A>
{
}

//this fails at compile time as B does not inherit from Control class.
public class B : IEmbed<B>
{
}
0 голосов
/ 26 марта 2012

На самом деле я не могу себе представить, зачем вам это нужно, но Control является потомком IComponent. Может быть, вы должны наследовать от этого?

0 голосов
/ 26 марта 2012

Что не использует декларацию, а проверка T является контролем?

Кроме того, я согласен с тем, что написано выше, почему интерфейс должен быть типом? Кажется, что это плохой дизайн, когда вы знаете, что позже вы вернете свой интерфейс обратно в элемент управления ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...