C
C#3mo ago
Mekasu0124

✅ Which is the more correct way of class instantiation?

// app.axaml.cs
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
Helpers hp = new();

desktop.MainWindow = new MainWindow
{
DataContext = new MainWindowViewModel(hp),
};
}

base.OnFrameworkInitializationCompleted();
}
// app.axaml.cs
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
Helpers hp = new();

desktop.MainWindow = new MainWindow
{
DataContext = new MainWindowViewModel(hp),
};
}

base.OnFrameworkInitializationCompleted();
}
// MainWindowViewModel.cs
public class MainWindowViewModel : ViewModelBase
{
private Helpers _hp = new();

// this part is 100% optional. You can use helpers as _hp as well
public Helpers Hp
{
get => _hp;
set => this.RaiseAndSetIfChanged(ref _hp, value);
}
}
// MainWindowViewModel.cs
public class MainWindowViewModel : ViewModelBase
{
private Helpers _hp = new();

// this part is 100% optional. You can use helpers as _hp as well
public Helpers Hp
{
get => _hp;
set => this.RaiseAndSetIfChanged(ref _hp, value);
}
}
Is it better to instantiate your used objects like this in the app.axaml.cs file and then pass them off to the main window view model like the public override function at the top or is it better to instantiate your used objects in the main window view model like the code block underneath it? I ask because I've noticed that when I build a new view model, if I instantiate the items I need right there in the class as new instances of that item, I don't have the need for two constructors like
public MainWindowViewModel()
{
Text = "Hello World!";
}
public MainWindowViewModel(Helpers hp)
{
_hp = hp;
}
public MainWindowViewModel()
{
Text = "Hello World!";
}
public MainWindowViewModel(Helpers hp)
{
_hp = hp;
}
so I'm just curious to if it's user preference, or which is more correct
12 Replies
Pobiega
Pobiega3mo ago
Depends on a few things. First, the parameterless constructor implies that the helper object is optional But it's not declared as such, so that's an orange flag. However, beyond that it's really up to you if you want to do inversion of control or not
Mekasu0124
Mekasu01243mo ago
the only reason I have two constructors is because when I pass variables from the previous file to the next file, I get an error saying that the view model can't find a good enough constructor I forgot to put the : this() on the one that is supposed to be called
Pobiega
Pobiega3mo ago
Taking the dependency as a constructor parameter let's you easily use DI for example But if you dont plan on using DI, there isn't much to win
Mekasu0124
Mekasu01243mo ago
DI means dependency injection, right?
Pobiega
Pobiega3mo ago
Yup
Mekasu0124
Mekasu01243mo ago
so passing the instance from app.axaml.cs to MWVM is DI when I use that passed object in the MWVM ok so I'm still not quite satisfied. Which is better? DI or new instantiations in each view model and other classes (creating multiple instances)?
Pobiega
Pobiega3mo ago
Depends. Does the helper class have internal state that shouldn't be mixed across multiple windows? If it does, don't inject the same instance If it doesn't, can the helper be static?
Mekasu0124
Mekasu01243mo ago
public class Helpers
{
private static readonly string _tosPath = Directory.GetCurrentDirectory() + "/MakeMyProject/TermsOfService.txt";

internal string GetTosText()
{
var fileData = File.ReadAllText(_tosPath);

if (fileData != null)
{
return fileData;
}
else
{
return """
No Tos Text Was Found

If you believe this to be in error then try restarting
the program, otherwise, please create a new issue on
the github repo page.

-Mekasu
""";
}
}
}
public class Helpers
{
private static readonly string _tosPath = Directory.GetCurrentDirectory() + "/MakeMyProject/TermsOfService.txt";

internal string GetTosText()
{
var fileData = File.ReadAllText(_tosPath);

if (fileData != null)
{
return fileData;
}
else
{
return """
No Tos Text Was Found

If you believe this to be in error then try restarting
the program, otherwise, please create a new issue on
the github repo page.

-Mekasu
""";
}
}
}
this is one of my helper files. The other one is a JsonEngine which is a public class with internal functions
Pobiega
Pobiega3mo ago
This one seems as if it could be static, techically but if we disregard that and speak about the concept generally, I'd usually recommend passing them in via the constructor, as it gives more freedom you can tweak what VMs share what dependencies as you need - new every time, partial sharing, full sharing, etc
Mekasu0124
Mekasu01243mo ago
gotcha. thanks! just to be sure I understand the lingo.
This one seems as if it could be static, technically
public class MainWindowViewModel : ViewModelBase
{
ViewModelBase _content = new();

- private Helpers _hp = new();
- private JsonEngine _jsEngine = new();

- public MainWindowViewModel(Helpers hp, JsonEngine jsEngine)
+ public MainWindowViewModel()
{
- UsersModel model = JsEngine.CreateUsersFile();
+ UsersModel model = JsonEngine.CreateUsersFile();
}

- public Helpers Hp
- {
- get => _hp;
- set => this.RaiseAndSetIfChanged(ref _hp, value);
- }

- public JsonEngine JsEngine
- {
- get => _jsEngine;
- set => this.RaiseAndSetIfChanged(ref _jsEngine, value);
- }
}
public class MainWindowViewModel : ViewModelBase
{
ViewModelBase _content = new();

- private Helpers _hp = new();
- private JsonEngine _jsEngine = new();

- public MainWindowViewModel(Helpers hp, JsonEngine jsEngine)
+ public MainWindowViewModel()
{
- UsersModel model = JsEngine.CreateUsersFile();
+ UsersModel model = JsonEngine.CreateUsersFile();
}

- public Helpers Hp
- {
- get => _hp;
- set => this.RaiseAndSetIfChanged(ref _hp, value);
- }

- public JsonEngine JsEngine
- {
- get => _jsEngine;
- set => this.RaiseAndSetIfChanged(ref _jsEngine, value);
- }
}
right?
Pobiega
Pobiega3mo ago
Yeah, pretty much
Mekasu0124
Mekasu01243mo ago
ok bet. ty