Сама проблема здесь довольно проста, но все решения кажутся плохими, поэтому я не могу решить, какой из них лучше, поэтому подумал, что мне следует спросить здесь ...
В настоящее время я обертываю несколько компонентов XNA (SpriteBatch, GraphicsDevice, ContentLoader и т. Д.), По большей части они оборачивают все 1-1, но есть несколько отличий, когда необязательные аргументы сокращают перегрузку функций. Это в основном делается для того, чтобы включить Dependency Injection и позволить мне намного проще имитировать тесты, так как я предпочел бы использовать шаблон внедрения, а не шаблон локатора службы (хотя я также создал NinjectServiceProvider, который реализует IServiceProvider).
В любом случае, главная проблема здесь в том, что мне нужно обновить несколько разных объектов ISpriteBatch из-за разных компонентов, использующих разные режимы наложения и т. Д. Поэтому я создал новый объект SpriteBatchFactory. Прежде чем продолжить, приведу несколько примеров фрагментов, чтобы вы могли видеть, откуда я иду:
public class MySpriteBatch : ISpriteBatch
{
private SpriteBatch underlyingSpriteBatch;
private IGraphicsDevice graphicsDevice;
public MySpriteBatch(SpriteBatch underlyingSpriteBatch,
IGraphicsDevice graphicsDevice)
{
this.underlyingSpriteBatch = underlyingSpriteBatch;
this.graphicsDevice = graphicsDevice;
}
// ...
}
MyGraphicsDevice:
public class MyGraphicsDevice : IGraphicsDevice
{
private GraphicsDevice underlyingGraphicsDevice;
public MyGraphicsDevice(GraphicsDevice underlyingDevice)
{
this.underlyingGraphicsDevice = underlyingDevice;
}
// ...
}
SpriteBatchFactory:
public class SpriteBatchFactory
{
public SpriteBatchFactory(IGraphicsDevice graphicsDevice)
{
this.GraphicsDevice = graphicsDevice;
}
public IGraphicsDevice GraphicsDevice { get; private set; }
public ISpriteBatch Create()
{
var underlyingGraphicsDevice = ????
var underlyingSpriteBatch =
new SpriteBatch(underlyingGraphicsDevice);
return new MySpriteBatch(underlyingSpriteBatch,
this.GraphicsDevice);
}
}
Теперь, как вы можете видеть, чтобы создать MySpriteBatch (ISpriteBatch), мне требуется новый SpriteBatch, для которого, в свою очередь, требуется экземпляр GraphicsDevice ... и я не уверен, как лучше удовлетворить эту зависимость ... A Вот несколько решений, о которых я подумал:
1) MyGraphicsDevice содержит это, но оно не раскрывается, поэтому я могу представить его как объект на уровне интерфейса или как реальный GraphicsDevice на уровне конкретного класса. В любом случае это потребует приведения типа объекта -> GraphicsDevice или IGraphicsDevice -> MyGraphicsDevice.
2) Я даю SpriteBatchFactory GraphicsDevice, а не IGraphicsDevice и новый, каждый раз, когда мне нужно обновить MySpriteBatch.
3) Я создаю MySpriteBatch для внутреннего создания SpriteBatch, для него требуется MyGraphicsDevice и выставляю его там, поэтому MySpriteBatch не имеет внешней зависимости от SpriteBatch.
Я думаю, что третий звучит более инкапсулированным способом сделать это, но мне не нравится ни один из способов, так может кто-нибудь еще придумает более хороший способ решить эту проблему? Меня не беспокоит наличие зависимостей XNA, так как я не пытаюсь создать эту кроссплатформенность, просто пытаюсь дать мне более управляемый слой между Xna и моей структурой.
=== Редактировать ===
Когда я говорю, что я обертываю базовые компоненты, я имею в виду буквально обертку вызовов, то есть:
public class MyGraphicsDevice : IGraphicsDevice
{
private GraphicsDevice underlyingGraphicsDevice;
public MyGraphicsDevice(GraphicsDevice underlyingDevice)
{
this.underlyingGraphicsDevice = underlyingDevice;
}
public VertexBuffer[] GetVertexBuffers()
{
return underlyingGraphicsDevice.GetVertexBuffers();
}
public void SetRenderTarget(RenderTarget2D renderTarget)
{
underlyingGraphicsDevice.SetRenderTarget(renderTarget);
}
// ...
}
Так что на самом деле никакой пользовательской логики нет, это просто глупая оболочка.