2015-04-03 2 views
1

У меня есть программа, которая должна иметь возможность взаимодействовать с несколькими платформами, то есть читать/записывать файлы, читать/писать базу данных или читать/писать веб-запросы. Интерфейс платформы выбирается из конфигурации и не изменяется во время работы приложения. У меня есть один класс интерфейса чтения/записи, который наследуется классами, специфичными для платформы, так что это абстрагируется от остальной части программы.Статический интерфейс C# или абстрактная реализация

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

Может ли кто-нибудь показать мне другой метод приближения к этой ситуации?

Edit: Спасибо за вход каждого, вот мое решение, основанное на данном примере Патрик Хофман

interface TheInterface 
{ 
    void read(); 
    void write(); 
} 


public class X : TheInterface 
{ 
    public void read() { //do something } 
    public void write() { //do something } 
} 

public class Y : TheInterface 
{ 
    public void read() { //do something } 
    public void write() { //do something } 
} 


public class FileAccessor 
{ 
    public static TheInterface accessor; 

    public static TheInterface Accessor 
    { 
     get 
     { 
      if(accessor) return accessor; 
     } 
    } 
} 

Это можно назвать любым классом, как (спасибо!):

static void Main(string[] args) 
{ 
    switch (Config.interface) 
    { 
     case "X": 
      FileAccessor.accessor = new Lazy<X>(); 
     case "Y": 
      FileAccessor.accessor = new Lazy<Y>(); 
     default: 
      throw new Lazy<Exception>("Unknown interface: " + Config.interface); 
    } 

    FileAccessor.Accessor.read(); 
} 
+0

Можете ли вы предоставить код о вашем сценарии ?! Я думаю, что вы могли бы достичь своей цели, используя абстрактный класс с видом шаблона проектирования. –

+0

1) Рассмотрите возможность использования инъекции зависимостей над одноэлементным узлом со статическим аксессуаром. 2) если вы настаиваете на этом типе, используйте 'Lazy ' для его реализации. 3) Почему 'GetLibrary()' public? – CodesInChaos

+0

Спасибо CodesInChaos, вы правы, что должны были быть частными. Сейчас я читаю «Инъекция зависимостей». Могли ли вы привести пример того, как это относится к моему коду? – Scotty

ответ

2

Действительно, интерфейсы или абстрактные классы не могут быть самими static, но дальнейшая реализация может. Кроме того, вы можете использовать одноплодную шаблон, чтобы сделать вашу жизнь проще, и позволить наследование и т.д.

public class X : ISomeInterface 
{ 
    private X() { } 

    public static X instance; 
    public static X Instance 
    { 
     get 
     { 
      return instance ?? (instance = new X()); 
     } 
    } 
} 

Или, используя Lazy<T>:

public class X : ISomeInterface 
{ 
    private X() { } 

    public static Lazy<X> instanceLazy = new Lazy<X>(() => new X()); 
    public static X Instance 
    { 
     get 
     { 
      return instance.Value; 
     } 
    } 
} 
+0

Я бы предпочел использовать 'Lazy ' за его простоту и безопасность потоков. – CodesInChaos

+0

Спасибо Патрику, я использовал модифицированную версию этой идеи в своем решении, которое я добавил к вопросу. Мне было бы интересно узнать, правильно ли я выполнил ваше решение или был ли лучший способ увидеть его? – Scotty

+0

@CodesInChaos: Согласен. Код был как общая идея. Будет обновляться. –

0

Вы можете сделать статический класс, который имеет переменный ваши Интерфейс.

public static class StaticClass 
    { 
    public static ISomeInterface Interface; 
    } 

Теперь вы можете получить доступ к экземпляру отовсюду в вашем Framwork

static void Main(string[] args) 
{ 
    StaticClass.Interface = new SomeClass(); 
} 
1

Отказ от ответственности: я являюсь автором библиотеки, описанной ниже.

Я не знаю, если это поможет, но я написал a library (очень ранняя версия пока), что позволяет определить статические интерфейсы, определяя обычные интерфейсы и украшая их методы с атрибутом имени [Static], например, :

public interface IYourInterface 
{ 
    [Static] 
    void DoTheThing(); 
} 

(Обратите внимание, что вы явно не добавить этот интерфейс для ваших реализаций.)

После того, как вы определили интерфейс, вы можете создать его экземпляр из вашего кода с любой действительной реализацией вы выбираете:

return typeof(YourImplementation).ToStaticContract<IYourInterface>(); 

Если методы не найдены в YourImplementation, этот вызов завершается с ошибкой во время выполнения с исключением.

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

IYourInterface proxy = GetAnImplementation(); 
proxy.DoTheThing(); 
+0

Спасибо, что поделились этим. Поскольку мне это будет единственный раз, когда мне нужно это сделать во время этого проекта, я не буду использовать дополнительную библиотеку, однако я уверен, что другие найдут это полезным. – Scotty

Смежные вопросы