diff --git a/Common/StartupHelpers/AbstractFactory.cs b/Common/StartupHelpers/AbstractFactory.cs index 84cefe8..1331523 100644 --- a/Common/StartupHelpers/AbstractFactory.cs +++ b/Common/StartupHelpers/AbstractFactory.cs @@ -7,16 +7,16 @@ public class AbstractFactory : IAbstractFactory /// /// Constructor for Abstract Factory. /// - /// Function of the factory + /// factory function public AbstractFactory(Func factory) { this.factory = factory; } /// - /// Executes factory function and returns it. + /// Executes factory function and returns instanciated object. /// - /// Factory + /// created object public T Create() { return factory(); diff --git a/Common/StartupHelpers/ServiceExtensions.cs b/Common/StartupHelpers/ServiceExtensions.cs index f4493e1..ce48501 100644 --- a/Common/StartupHelpers/ServiceExtensions.cs +++ b/Common/StartupHelpers/ServiceExtensions.cs @@ -4,6 +4,24 @@ namespace Common.StartupHelpers; public static class ServiceExtensions { + /// + /// Service Extension to add an to Dependency Injection. + /// + /// Type of interface + /// Type of implementation + /// existing service collection + public static void AddAbstractFactory(this IServiceCollection services) + where TInterface : class + where TImplementation : class, TInterface + { + // add implementation to services collection + services.AddTransient(); + // add factory function to services collection + services.AddSingleton>(x => () => x.GetService()!); + // add factory implementation to services collection + services.AddSingleton, AbstractFactory>(); + } + /// /// Adds a factory for subcontrols to be created. /// For example a UserControl can be instanciated using this Service. @@ -14,7 +32,7 @@ public static class ServiceExtensions { // add to DI: the subcontrol itself services.AddTransient(); - // add to DI: Func of that subcontrol, that will create the subcontrol + // add to DI: Func of constructor of that subcontrol services.AddSingleton>(x => () => x.GetService()!); // add to DI: Factory for the subcontrol services.AddSingleton, AbstractFactory>(); diff --git a/MultiTerm.Core/Factories/ITerminalViewModelFactory.cs b/MultiTerm.Core/Factories/ITerminalViewModelFactory.cs new file mode 100644 index 0000000..63b09f6 --- /dev/null +++ b/MultiTerm.Core/Factories/ITerminalViewModelFactory.cs @@ -0,0 +1,10 @@ +using MultiTerm.Core.Common; +using MultiTerm.Core.ViewModel; + +namespace MultiTerm.Core.Factories +{ + public interface ITerminalViewModelFactory + { + ITerminalViewModel Create(TerminalViewType viewType, ProtocolType protocolType); + } +} \ No newline at end of file diff --git a/MultiTerm.Core/Factories/TerminalViewModelFactory.cs b/MultiTerm.Core/Factories/TerminalViewModelFactory.cs new file mode 100644 index 0000000..3c9566c --- /dev/null +++ b/MultiTerm.Core/Factories/TerminalViewModelFactory.cs @@ -0,0 +1,51 @@ +using MultiTerm.Core.Common; +using MultiTerm.Core.ViewModel; + +namespace MultiTerm.Core.Factories; + +/// +/// Can create instances during runtime. +/// +public class TerminalViewModelFactory : ITerminalViewModelFactory +{ + private readonly Func> factory; + + /// + /// Constructor of . + /// + /// function that gets all registered services with Interface + public TerminalViewModelFactory(Func> factory) + { + this.factory = factory; + } + + /// + /// Creates a new . + /// + /// of the new . Must be set at creation time for all + /// of the new + /// + public ITerminalViewModel Create(TerminalViewType viewType, ProtocolType protocolType) + { + ITerminalViewModel output; + + // get all registered TerminalViewModels as IEnumerable + var registeredViewModels = factory(); + + // search for correct type by ViewType which must be set in constructor of all TerminalViewModel Types + try + { + output = registeredViewModels.Where(x => x.ViewType == viewType).First(); + } + catch (Exception ex) + { + throw new NotImplementedException($"'{nameof(TerminalViewModelFactory)}' cannot create Terminal with {nameof(TerminalViewType)} {viewType}", ex); + } + + // immediately initialize protocol type + output.ProtocolType = protocolType; + + // return the filled up instance + return output; + } +} diff --git a/MultiTerm.Core/Helpers/ServiceExtensions.cs b/MultiTerm.Core/Helpers/ServiceExtensions.cs new file mode 100644 index 0000000..224e8f2 --- /dev/null +++ b/MultiTerm.Core/Helpers/ServiceExtensions.cs @@ -0,0 +1,27 @@ +using Microsoft.Extensions.DependencyInjection; +using MultiTerm.Core.Factories; +using MultiTerm.Core.ViewModel; + +namespace MultiTerm.Core.Helpers; + +public static class ServiceExtensions +{ + /// + /// Service Extension to add all implementations of to Dependency Injection. + /// Also adds to Dependency injection, which allows instanciation of during runtime. + /// + /// existing services collection + public static void AddTerminalViewModelFactory(this IServiceCollection services) + { + // add all implementations to the services collection + services.AddTransient(); + // TODO extend + + // add a function to the services collection, which is used by the TerminalViewModelFactory + // to get a list of all registered implementations of ITerminalViewModel + services.AddSingleton>>(x => () => x.GetService>()!); + + // add the factory itself to the services collection + services.AddSingleton(); + } +} diff --git a/MultiTerm.Core/ViewModel/ITerminalViewModel.cs b/MultiTerm.Core/ViewModel/ITerminalViewModel.cs index 52db3f6..c8b18c3 100644 --- a/MultiTerm.Core/ViewModel/ITerminalViewModel.cs +++ b/MultiTerm.Core/ViewModel/ITerminalViewModel.cs @@ -17,7 +17,7 @@ public interface ITerminalViewModel /// /// Type of Protocol. /// - ProtocolType ProtocolType { get; } + ProtocolType ProtocolType { get; set; } /// /// Request Closing of Terminal. diff --git a/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs b/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs index feb9da8..0467e90 100644 --- a/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs +++ b/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs @@ -4,12 +4,14 @@ namespace MultiTerm.Core.ViewModel; public partial class SendReceiveViewModel : TerminalViewModel { - public override string Title => "SendReceive Tab"; - public override TerminalViewType ViewType => TerminalViewType.SendReceive; - - public SendReceiveViewModel() : base(ProtocolType.Serial) // TODO implement Protocol initialization + public override string Title { - + get + { + return $"{ViewType} {ProtocolType}"; + } } + public override TerminalViewType ViewType => TerminalViewType.SendReceive; + } diff --git a/MultiTerm.Core/ViewModel/ShellViewModel.cs b/MultiTerm.Core/ViewModel/ShellViewModel.cs index 8410f8c..5823144 100644 --- a/MultiTerm.Core/ViewModel/ShellViewModel.cs +++ b/MultiTerm.Core/ViewModel/ShellViewModel.cs @@ -2,14 +2,13 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using MultiTerm.Core.Common; +using MultiTerm.Core.Factories; using System.Collections.ObjectModel; namespace MultiTerm.Core.ViewModel; public partial class ShellViewModel : ObservableObject { - private readonly IAbstractFactory sendReceiveViewModelFactory; - [ObservableProperty] private string title = "ShellView Test"; @@ -35,17 +34,17 @@ public partial class ShellViewModel : ObservableObject #endregion - public ShellViewModel(IAbstractFactory sendReceiveViewModelFactory) + private readonly ITerminalViewModelFactory terminalViewModelFactory; + + public ShellViewModel(ITerminalViewModelFactory terminalViewModelFactory) { - this.sendReceiveViewModelFactory = sendReceiveViewModelFactory; - // create a new terminal - this.AppendConfiguredTerminal(this.sendReceiveViewModelFactory.Create()); + this.terminalViewModelFactory = terminalViewModelFactory; } [RelayCommand] private void AppendTerminalWithSelectedViewType(ProtocolType protocolType) { - Console.WriteLine($"Type = {protocolType}"); + this.AppendConfiguredTerminal(this.terminalViewModelFactory.Create(this.SelectedTerminalViewType, protocolType)); } @@ -57,6 +56,7 @@ public partial class ShellViewModel : ObservableObject // add to collection and register closing event handler this.TerminalViewModels.Add(newTerminal); newTerminal.ClosingEvent += Terminal_ClosingEvent; + // set as selected this.SelectedTerminalViewModel = newTerminal; } diff --git a/MultiTerm.Core/ViewModel/TerminalViewModel.cs b/MultiTerm.Core/ViewModel/TerminalViewModel.cs index 14a84cd..9af35e4 100644 --- a/MultiTerm.Core/ViewModel/TerminalViewModel.cs +++ b/MultiTerm.Core/ViewModel/TerminalViewModel.cs @@ -8,15 +8,10 @@ public abstract partial class TerminalViewModel : ObservableObject, ITerminalVie { public abstract string Title { get; } public abstract TerminalViewType ViewType { get; } - public ProtocolType ProtocolType { get; private set; } + public ProtocolType ProtocolType { get; set; } public event EventHandler? ClosingEvent; - public TerminalViewModel(ProtocolType protocolType) - { - this.ProtocolType = protocolType; - } - /// /// Method to override if any closing actions are required. /// Closing can be cancelled using the return value. diff --git a/MultiTerm.Wpf/App.xaml.cs b/MultiTerm.Wpf/App.xaml.cs index ea899db..cc8e2ae 100644 --- a/MultiTerm.Wpf/App.xaml.cs +++ b/MultiTerm.Wpf/App.xaml.cs @@ -4,6 +4,7 @@ using MultiTerm.Core.ViewModel; using Common.StartupHelpers; using System.Windows; using MultiTerm.Core.Common; +using MultiTerm.Core.Helpers; namespace MultiTerm.Wpf; @@ -22,8 +23,8 @@ public partial class App : Application // viewmodels services.AddSingleton(); - // subcontrols - services.AddSubControlFactory(); + // application specific + services.AddTerminalViewModelFactory(); }) .Build(); } diff --git a/MultiTerm.Wpf/View/ShellView.xaml b/MultiTerm.Wpf/View/ShellView.xaml index 0ce3b5e..a4568e8 100644 --- a/MultiTerm.Wpf/View/ShellView.xaml +++ b/MultiTerm.Wpf/View/ShellView.xaml @@ -95,17 +95,6 @@ Command="{Binding Data.AppendTerminalWithSelectedViewTypeCommand, Source={StaticResource proxy}}" CommandParameterType="{x:Type core_common:ProtocolType}"> - -