C# 在不同的游戏引擎实现组件中填充SharpDX和OpenTK?
我希望我的C#引擎能够让用户在使用Direct3D或OpenGL之间进行选择。 我的引擎的内部设计与着色器类的抽象示例类似:C# 在不同的游戏引擎实现组件中填充SharpDX和OpenTK?,c#,.net-assembly,extensibility,C#,.net Assembly,Extensibility,我希望我的C#引擎能够让用户在使用Direct3D或OpenGL之间进行选择。 我的引擎的内部设计与着色器类的抽象示例类似: internal class Shader { private IShaderImplementation _implementation; internal Shader(ShaderType type, string code) { switch (Engine.GraphicsInterface) {
internal class Shader
{
private IShaderImplementation _implementation;
internal Shader(ShaderType type, string code)
{
switch (Engine.GraphicsInterface)
{
case GraphicsInterface.Direct3D:
_implementation = new Direct3DShader(type, code);
break;
case GraphicsInterface.OpenGL:
_implementation = new OpenGLShader(type, code);
break;
default:
throw new UnsupportedInterfaceException("Shader");
break;
}
}
internal void Compile()
{
_implementation.Compile();
}
}
我认为这是一个很好的设计模式。(正如您可能已经注意到的,我也更喜欢调用构造函数而不是工厂方法,但这只是一件次要的事情)
然而:
- 我不想将OpenTK(用于OpenGL)程序集引用与SharpDX(用于Direct3D)程序集引用一起填充到一个类库中。我甚至不知道这是不是个好主意。从当前设计来看,这是必需的,因为Direct3DShader和OpenGLShader类直接引用D3D或OGL方法。即使用户只希望使用OpenGL,我是否需要同时发布OpenTK/SharpDX程序集
- 我希望有一个主程序集只包含上面提到的通用接口内容(比如“可怕的.Engine.dll”,另一个只包含OpenGL内容(“可怕的.Engine.OpenGL.dll”),另一个用于Direct3D内容(“可怕的.Engine.Direct3D”)。但是如何在主程序集中引用它?正如您所看到的,我有一个接口枚举,这将不再有效
PS:我听说过关于反射的事,我只知道一两分钱,然后是托管扩展性框架,但我还没有弄清楚它如何适合我的设计。将它设计为3个类库,用于图形层和声音层 类库1:接口层
- 包含包装器将实现的所有包装器和接口
- 设计接口,使其在自己的应用程序域中工作,并为所有内容分发接口
- 引用类库1和OpenTK
- 添加一个像OpenAL这样的声音API
- 实现封装对OpenTK的调用并播放声音的接口
- 参考类库1和Sharp DX
- 实现封装对SharpDX的调用并通过SharpDX播放声音的接口
- 向类库1添加一个硬引用,这样您就拥有了所有接口类型、枚举等
- 使用反射动态加载类库2或类库3
- 为硬件层创建新的应用程序域
- 使用
加载类库2或类库3AppDomain.Load
- 加载硬件程序集并拥有
对象后,使用反射获取对接口的引用,可能类似以下内容:assembly
// Making up this pseudo code GameApi gameApi = (GameApi)hardwareAsm.GetType(GameApi).GetMethod("Initialize").Invoke(); TheGame gameWorld = gameApi.CreateGame(...); gameWorld.ResolutionChanged += Resolution_Changed(...); gameWorld.Terminated += Terminated(...); gameWorld.KeyDown += Key_Down(...); // etc.... gameWorld.Start();
- 可以卸载应用程序域,从而也可以卸载它们加载的任何程序集。(如果用户可以在运行时从DirectX切换到OpenGL,这将是必需的,这将是整洁和可能的,我以前从未见过有人这样做)
- 应用程序域可以使用自己的安全描述符、ACE等进行保护。例如,您可以阻止应用程序域中运行的代码访问创建文件、发出internet请求等(如果您正在为游戏加载项设计插件层,则非常有用)
- 可以编写应用程序域,使其能够正常崩溃、记录崩溃并在不影响根进程的情况下重新启动