C
C#7mo ago
chronos

make game obj accessible in other classes?

No description
12 Replies
chronos
chronos7mo ago
No description
chronos
chronos7mo ago
No description
chronos
chronos7mo ago
No description
chronos
chronos7mo ago
i want to be able to access the game obj from anywhere in my program how would i be able to do this?
Angius
Angius7mo ago
Best way? Dependency injection. Easiest way? Create an instance of Game at the start, and keep it in a static variable Another easy and slightly better way? Instantiate Game at the start and pass it around.
chronos
chronos7mo ago
will try, thank you!
Mayor McCheese
Mayor McCheese7mo ago
I think there's no out of the box tooling for di in winforms. I imagine it's fairly trivial to build up though.
Angius
Angius7mo ago
Could prolly hook up Autofac or Ms.DependencyInjection fairly easily
chronos
chronos7mo ago
i dunno what this means specifically but i could look it up : p
Mayor McCheese
Mayor McCheese7mo ago
I got some quick and easy traction, but things definitely fall apart.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace DISample;

static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
ApplicationConfiguration.Initialize(); // DO ME FIRST

var host = Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddSingleton<Form1>();
services.AddTransient<Form2>();
services.AddSingleton<Form3>(); // <-- This guy is a problem, because if I close the form it gets disposed; so my singleton is disposed.
services.AddSingleton<IFormFactory, FormFactory>();
services.AddSingleton<GameState>();
}).Build();

using var scope = host.Services.CreateScope();

var form1 = scope.ServiceProvider.GetRequiredService<Form1>();

// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
Application.Run(form1);
}
}

public interface IFormFactory
{
T CreateForm<T>() where T : Form;
}

public class FormFactory : IFormFactory
{
private readonly IServiceProvider _serviceProvider;

public FormFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}

public T CreateForm<T>() where T : Form
{
return _serviceProvider.GetRequiredService<T>(); // trying to sort of avoid service locator pattern coupled with deliberate DI
}
}
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace DISample;

static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
ApplicationConfiguration.Initialize(); // DO ME FIRST

var host = Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddSingleton<Form1>();
services.AddTransient<Form2>();
services.AddSingleton<Form3>(); // <-- This guy is a problem, because if I close the form it gets disposed; so my singleton is disposed.
services.AddSingleton<IFormFactory, FormFactory>();
services.AddSingleton<GameState>();
}).Build();

using var scope = host.Services.CreateScope();

var form1 = scope.ServiceProvider.GetRequiredService<Form1>();

// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
Application.Run(form1);
}
}

public interface IFormFactory
{
T CreateForm<T>() where T : Form;
}

public class FormFactory : IFormFactory
{
private readonly IServiceProvider _serviceProvider;

public FormFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}

public T CreateForm<T>() where T : Form
{
return _serviceProvider.GetRequiredService<T>(); // trying to sort of avoid service locator pattern coupled with deliberate DI
}
}
There's probably a "winforms way" to solve the disposed object issue on a singleton form So I ended up with this nasty bit of code on the first try; it "works" in a naive sample
public class SingletonForm : Form
{
protected SingletonState State = SingletonState.On;

protected override void OnFormClosing(FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
this.Hide();
return;
}

State = SingletonState.Disposing;
base.OnFormClosing(e);
}

protected override void Dispose(bool disposing)
{
if (State == SingletonState.On)
{
return;
}

base.Dispose(disposing);
}

protected enum SingletonState
{
On,
Disposing
}
}
public class SingletonForm : Form
{
protected SingletonState State = SingletonState.On;

protected override void OnFormClosing(FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
this.Hide();
return;
}

State = SingletonState.Disposing;
base.OnFormClosing(e);
}

protected override void Dispose(bool disposing)
{
if (State == SingletonState.On)
{
return;
}

base.Dispose(disposing);
}

protected enum SingletonState
{
On,
Disposing
}
}
Here is my naive example : @chronos @ZZZZZZZZZZZZZZZZZZZZZZZZZ https://github.com/devdevdeveau/winforms-di-sample
chronos
chronos7mo ago
thank you!
Mayor McCheese
Mayor McCheese7mo ago
You're welcome to steal all the ideas there. Which it's a public repo; should be a given