Как правильно отделить классы от фреймворков (развязка исходного уровня) - PullRequest
5 голосов
/ 03 декабря 2011

Я работаю над игровым проектом с использованием платформы Microsoft XNA, хотя этот вопрос является общим, который включает разделение классов / систем.

Допустим, у меня есть класс (упрощенный в соответствии с этим примером) какпоказано здесь:

public class GameCell
{   
        public Color Color { get; set; }
}

Я хотел бы использовать как можно больше кода между несколькими платформами, использующими C #.

Проблема прямой ссылки на структуру Color заключается в том, что этот тип определен в сборках XNA, создавая сильную связь (или зависимость) между моим кодом и XNA.

Другой каркас, который я буду использовать, может (или не может) иметь свой собственный Объект Color с собственным набором свойств и API.

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

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

Это вообще возможно сделать?Как бы вы предложили сохранить такую ​​систему переносимой?

Я видел несколько случаев (в разработке на C ++), когда вы определяете набор классов, которые отражают классы, которые использует используемая вами структура (дляпример здесь - снова определите Color), и, таким образом, можно «переназначить» это позже, чтобы использовать другие классы при необходимости.

Другой вариант - возиться с использованием #IFDEF, чтобы поиграть с использованиемоператоры в заголовке класса (переход с XNA на другие платформы).Какова лучшая альтернатива в этом случае?

1 Ответ

5 голосов
/ 03 декабря 2011

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

#define USE_DOTNET
//#define USE_SOMETHINGELSE

#if USE_DOTNET
using System.Drawing;
#endif

#if USE_SOMETHINGELSE
using SomethingElse.Drawing;
#endif

public struct MyColor
{
    #if USE_DOTNET
    Color TheColor;
    #endif
    #if USE_SOMETHINGELSE
    SomethingsColor TheColor;
    #endif

    public int R
    {
        get
        {
            #if USE_DOTNET
                // code to return .NET Color.R value
            #endif
            #if USE_SOMETHINGELSE
                // code to return SomethingColor.R value
            #endif
         }
    }
}

Другим способом является выделение отдельных областей для кода .NET и SomethingElse.Например:

#if USE_DOTNET
public int R
{
    get { return TheColor.R; }
}
// other properties and methods here
#endif

#if USE_SOMETHINGELSE
// properties and methods for using SomethingElse
#endif

Это может хорошо работать, но вы должны быть очень осторожны при написании кода, чтобы не использовать структуру .NET Color где-либо, кроме этих слоев переносимости.

Мы использовали эту технику в C / C ++ при разработке игр, которые должны были работать на Windows, Mac и нескольких различных игровых консолях.Сложно настроить слои переносимости, но как только они настроены, их довольно просто использовать.

Однако я бы предостерегал вас не давать вашим классам переносимости и структурам такие же имена, как у классовили структуры из библиотек .NET или других библиотек, которые вы используете.Если вы сделаете это, вы запутаетесь, и вы, скорее всего, напишите некоторый непереносимый код, который вы не обнаружите, пока не начнете пытаться его портировать.(Не то, что я говорю из опыта или чего-то еще.)

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