Permalink
Browse files

WindowsUniversal: added the possibility to initialize Game derived cl…

…ass with a rich constructor (closes #6288)
  • Loading branch information...
FrancescoBonizzi authored and cra0zy committed Oct 1, 2018
1 parent 15c201e commit ebcac5888d71069b67c6005a319490ce9dba91c7
@@ -0,0 +1,43 @@
# Game class constructor
Due to some UWP implementation details, Monogame has to construct your `Game` derived class by itself, using a static initializer `MonoGame.Framework.XamlGame<T>.Create(...)`.

In this situation, you have two main possibilities to create a `Game` derived class:

1. Let `XamlGame` initialize your `Game` derived class using the default constructor
2. Let `XamlGame` initialize your `Game` derived class using a custom constructor.

#### 1. XamlGame uses the default constructor

With this logic, it isn't possible to inject dependencies through the constructor since the default constructor is called:
`var game = new T();`



#### 2. XamlGame uses a custom constructor

Why may you need this constructor?

Consider `Game1` needs some dependencies such as an `ISettingsRepository` to get some values from each *platform* settings store. You would then implement an `AndroidSettingsRepository` and a `UwpSettingsRepository`, but you cannot construct those dependencies in `Game1` itself, **because they are platform dependent**, so you'll have to inject them into its constructor.

For example, in a `MainActivity` on Android you would do:

```c#
_game = new Game1(
new AndroidTextFileImporter(Assets),
new AndroidSettingsRepository(this));
```

With the UWP implementation using `XamlGame` static initializer, you could do this:

```c#
_game = MonoGame.Framework.XamlGame<Game1>.Create(
launchArguments,
Window.Current.CoreWindow,
swapChainPanel,
() => new Game1(
new UwpTextFileImporter(Assets),
new UwpSettingsRepository(this)));
```

In this way, you tell the static initializer **how** you'd like to construct `Game1`.

@@ -55,6 +55,7 @@
<topic id="Platform_Specific_Notes" name="Platform-Specific Notes" filename="platform_specific.md">
<topic id="Android" name="Android" filename="android.md"/>
<topic id="tvOS" name="tvOS" filename="tvOS.md"/>
<topic id="UWP" name="UWP" filename="UWP.md"/>
</topic>

<topic id="External_Links" name="External Links" filename="links.md"/>
@@ -2,3 +2,4 @@ While MonoGame aims to provide a platform-agnostic framework for developing game

- [Android](android.md)
- [tvOS](tvOS.md)
- [Windows Universal Platform (UWP)](UWP.md)
@@ -13,7 +13,7 @@ namespace MonoGame.Framework
/// <summary>
/// Static class for initializing a Game object for a XAML application.
/// </summary>
/// <typeparam name="T">A class derived from Game.</typeparam>
/// <typeparam name="T">A class derived from Game with a public parameterless constructor.</typeparam>
[CLSCompliant(false)]
public static class XamlGame<T>
where T : Game, new()
@@ -24,9 +24,24 @@ public static class XamlGame<T>
/// <param name="launchParameters">The command line arguments from launch.</param>
/// <param name="window">The core window object.</param>
/// <param name="swapChainPanel">The XAML SwapChainPanel to which we render the scene and receive input events.</param>
/// <returns></returns>
/// <returns>Returns an instance of T generated with default parameterless T constructor</returns>
static public T Create(string launchParameters, CoreWindow window, SwapChainPanel swapChainPanel)
{
return Create(() => new T(), launchParameters, window, swapChainPanel);
}

/// <summary>
/// Creates your Game class initializing it with <paramref name="gameConstructor"/> to work within a XAML application window.
/// </summary>
/// <param name="gameConstructor">The method to construct T</param>
/// <param name="launchParameters">The command line arguments from launch.</param>
/// <param name="window">The core window object.</param>
/// <param name="swapChainPanel">The XAML SwapChainPanel to which we render the scene and receive input events.</param>
/// <returns>Returns an instance of T generated with <paramref name="gameConstructor"/></returns>
static public T Create(Func<T> gameConstructor, string launchParameters, CoreWindow window, SwapChainPanel swapChainPanel)
{
if (gameConstructor == null)
throw new NullReferenceException(nameof(gameConstructor));
if (launchParameters == null)
throw new NullReferenceException("The launch parameters cannot be null!");
if (window == null)
@@ -37,11 +52,11 @@ static public T Create(string launchParameters, CoreWindow window, SwapChainPane
// Save any launch parameters to be parsed by the platform.
UAPGamePlatform.LaunchParameters = launchParameters;

// Setup the window class.
UAPGameWindow.Instance.Initialize(window, swapChainPanel, UAPGamePlatform.TouchQueue);
// Setup the window class.
UAPGameWindow.Instance.Initialize(window, swapChainPanel, UAPGamePlatform.TouchQueue);

// Construct the game.
var game = new T();
var game = gameConstructor();

// Set the swap chain panel on the graphics mananger.
if (game.graphicsDeviceManager == null)
@@ -54,5 +69,6 @@ static public T Create(string launchParameters, CoreWindow window, SwapChainPane
// Return the created game object.
return game;
}

}
}

0 comments on commit ebcac58

Please sign in to comment.