如何正确地将类与框架解耦(源码级解耦)

发布于 2024-12-19 02:00:01 字数 671 浏览 5 评论 0原文

我正在使用 Microsoft XNA 框架开发一个游戏项目,尽管这个问题是一个涉及类/系统解耦的通用问题。

假设我有一个类(经过简化以适合此示例),如下所示:

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

我想在使用 C# 的多个平台之间重用尽可能多的代码。

直接引用 Color 结构的问题是该类型是在 XNA 程序集中定义的,在我的代码和 XNA 之间创建了强耦合(或依赖)。

我将使用的另一个框架可能(也可能没有)有自己的 Color 对象,以及自己的一组属性和 API。

我想让相同的源文件“知道”自动使用 XNA 或其他框架的实现。

我知道其他类型的解耦方法,例如 IoC,但这意味着我将插入不同版本的系统/类,而不是在不同的上下文中重用同一类。

这可能吗?你建议如何保持这样一个系统的便携性?

我见过一些情况(在本机 C++ 开发中),您可以定义一组类来镜像您正在使用的框架所具有的类(例如此处 - 再次定义颜色),因此可以“重新定义颜色”。映射”,稍后根据需要使用不同的类。

另一种选择是使用 #IFDEF 来处理类头中的 using 语句(从 XNA 切换到其他平台)。 在这种情况下最好的选择是什么?

I am working on a game project using Microsoft XNA framework, although this question is a generic one that involves decoupling of classes/systems.

Let's say i have a class (simplified to suit this example) as shown here:

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

I would like to reuse as much code as i can between multiple platforms that use C#.

The problem of directly referncing the Color struct is that this type is defined in the XNA assemblies, creating a strong coupling (or dependency) between my code and XNA.

The other framework i will be using may (or may not) have its own Color object, with its own set of properties and API.

I would like to have the same source file "know" to use either the XNA or other framework's implementation automagically.

I know other types of decoupling methods such as IoC, but that would mean i would be plugging in different versions of a system/class, instead of reusing the same class in different contexts.

Is this even possible to do? how would u suggest to keep such a system portable?

I've seen some cases (in native C++ development) where you would define a set of classes that mirror the classes the framework you're using has (for example here - define Color again), and so it is possible to "re-map" this later on to use different classes, upon need.

Another option is to mess around using #IFDEF to play with the using statements in the header of the class (switching from XNA to other platforms).
What is the best alternative in this case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

熟人话多 2024-12-26 02:00:01

通常,您要做的是创建自己的 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 结构。

当开发必须在 Windows、Mac 和几种不同的游戏机上运行的游戏时,我们在 C/C++ 中使用了这种技术。设置可移植层很麻烦,但是一旦设置好,使用起来就非常容易了。

不过,我要提醒您,不要为您的可移植性类和结构指定与 .NET 库或您正在使用的其他库中的类或结构相同的名称。如果你这样做,你会让自己感到困惑,并且你可能会编写一些不可移植的代码,直到你开始尝试移植它时你才会发现它们。 (并不是说我是根据经验或其他什么来说话的......)

Typically what you do is create your own Color structure and have it do the translation using conditional compilation switches. For example:

#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
         }
    }
}

Another way is to have separate regions for the .NET and SomethingElse code. For example:

#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

This can work well, but you have to be very careful when writing your code so that you don't use the .NET Color structure anywhere but in these portability layers.

We used this technique in C/C++ when developing games that had to run on Windows, the Mac, and several different game consoles. It's a pain to set up the portability layers, but once they're set up, it's pretty easy to use.

I would caution you, though, not to give your portability classes and structures the same names as classes or structures from the .NET libraries or the other libraries you're using. If you do that, you're going to confuse yourself, and you're likely to write some non-portable code that you won't discover until you start trying to port it. (Not that I'm speaking from experience or anything . . .)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文