Beginner Question about implementing viewmodels #53
-
I have a Window that has a viewmodel, that has a shared service that uses another shared service. using Microsoft Extensions DI, I'd have something like
In the constructor for the window, I'd write How would I do this in Pure.DI? There's not many open sourceprojects using Pure.DI so I can't find many examples to learn from. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 8 replies
-
@AlexanderBlackman You can do exactly the same thing: using Pure.DI;
var window = new MyWindows();
interface ITodoDataProvider;
class DummyTodoDataProvider: ITodoDataProvider;
class TodoService;
class TinyTaskWindowViewModel;
class MyWindows
{
private readonly TinyTaskWindowViewModel _viewModel;
public MyWindows()
{
_viewModel = MyComposition.Default.Resolve<TinyTaskWindowViewModel>();
}
}
partial class MyComposition
{
public static readonly MyComposition Default = new();
private void Setup() =>
DI.Setup(nameof(MyComposition))
.Bind().As(Lifetime.Singleton).To<DummyTodoDataProvider>()
.Bind().As(Lifetime.Singleton).To<TodoService>()
.Bind().As(Lifetime.Singleton).To<TinyTaskWindowViewModel>()
.Root<TinyTaskWindowViewModel>();
} But this is not the best solution since your window will obviously create a view model using ServiceLocator's anti-pattern and will be aware of DI. It would be better if your view layer would know less - depend only on abstraction and not know about infrastructure. As far as I understand you are experimenting on a desktop application. Is it MAUI, WPF, Avalonia, WinForms or something else? There are some examples of using Pure.DI for different types of applications. Using a WPF application as an example the basic idea is as follows. You define a composition as a resource right in the markup: <Application x:Class="WpfAppNetCore.App" x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfAppNetCore="clr-namespace:WpfAppNetCore"
StartupUri="/Views/MainWindow.xaml"
Exit="OnExit">
<Application.Resources>
<wpfAppAppNetCore:Composition x:Key="Composition"/>
<Application.Resources>
</Application> And then use bindings to access the view model: <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{StaticResource Composition}"
Title="{Binding ClockViewModel.Time}">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding ClockViewModel}">
<TextBlock Text="{Binding Date}" FontSize="64" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding Time}" FontSize="128" HorizontalAlignment="Center"/>
</StackPanel>
</Window>. With this approach, all layers of the application remain as independent as possible:
If you share what kind of application you are interested in we can discuss in more detail. |
Beta Was this translation helpful? Give feedback.
-
I've done a lot of reading and experimentation today. I've managed to make compositions which inject a service simply by having an abstract in the constructor. Your library is very useful. I'm a bit confused about the composition root. I know the basic theory, but looking though the readme it appears there is a root for each parent service. Cheers |
Beta Was this translation helpful? Give feedback.
-
Another thing is in the example: internal class AppDataContext(
Lazy<MainWindow> mainWindow,
IClockViewModel clockViewModel)
{
public MainWindow MainWindow => mainWindow.Value;
public IClockViewModel ClockViewModel => clockViewModel;
} The |
Beta Was this translation helpful? Give feedback.
I didn't quite understand the question about composition roots. Let me tell you a little bit why composition roots are very important in Pure.DI and not so important in classic DI containers.
If you use classic DI containers, the composition is created dynamically every time you call a method similar to
T Resolve<T>()
or objectGetService(Type type)
. The root of the composition there is simply the root type of the composition of objects in memoryT
orType type
. There can be as many of these as you like.In the case of Pure.DI, the number of composition roots is limited because for each composition root a separate property or method is created at compile time. Therefore, each root is defi…