Skip to content

Commit

Permalink
Auto registering view models
Browse files Browse the repository at this point in the history
  • Loading branch information
nickrandolph committed Oct 12, 2020
1 parent ffe29fe commit d2e7ef1
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 44 deletions.
79 changes: 67 additions & 12 deletions BuildIt.Navigation.Generator/EventToNavigationMessageGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public void Execute(GeneratorExecutionContext context)
// the generator infrastructure will create a receiver and populate it
// we can retrieve the populated instance via the context
var syntaxReceiver = context.SyntaxReceiver as SyntaxReceiver;
if (string.IsNullOrWhiteSpace( syntaxReceiver?.AppServiceTypeName))
if (string.IsNullOrWhiteSpace(syntaxReceiver?.AppServiceTypeName))
{
return;
}
Expand Down Expand Up @@ -119,9 +119,25 @@ namespace {syntaxReceiver.AppServiceNamespace}
{{
public partial class {syntaxReceiver.AppServiceTypeName}
{{
partial void {syntaxReceiver.RegistrationPartialMethodName}(NavigationEvents events)
partial void {syntaxReceiver.RegistrationServicesPartialMethodName}(IServiceCollection serviceRegistrations)
{{
");

foreach (var reg in syntaxReceiver.AutoRegistrations)
{
sourceBuilder.AppendLine(
$@"
serviceRegistrations.AddTransient<{reg.ViewModelTypeName}>();
");
}

// finish creating the source to inject
sourceBuilder.Append($@"
}}
partial void {syntaxReceiver.RegistrationPartialMethodName}(NavigationEvents events)
{{
");

Expand Down Expand Up @@ -156,7 +172,7 @@ public partial class {syntaxReceiver.AppServiceTypeName}
// inject the created source into the users compilation
context.AddSource("MvvmApplicationServices.generated.cs", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8));
}
catch(Exception ex)
catch (Exception ex)
{

}
Expand All @@ -180,12 +196,17 @@ private class SyntaxReceiver : ISyntaxReceiver
public string AppServiceNamespace { get; set; }// => "MvvmNavigation";

public string RegistrationPartialMethodName { get; set; }// = "RegisterEvents";
public string RegistrationServicesPartialMethodName { get; set; }// = "RegisterEvents";

public string Namespaces => string.Join(Environment.NewLine, (from reg in Registrations
where reg.ParameterNamespace!=null
select reg.ParameterNamespace)
public string Namespaces => string.Join(Environment.NewLine,
(from reg in Registrations
where reg.ParameterNamespace != null
select reg.ParameterNamespace)
.Union(from reg in Registrations
where reg.ViewModelNamespace!=null
where reg.ViewModelNamespace != null
select reg.ViewModelNamespace)
.Union(from reg in AutoRegistrations
where reg.ViewModelNamespace != null
select reg.ViewModelNamespace)
.Distinct()
.OrderBy(x => x)
Expand All @@ -194,6 +215,8 @@ private class SyntaxReceiver : ISyntaxReceiver

public IList<EventRegistration> Registrations { get; } = new List<EventRegistration>();

public IList<ViewModelRegistration> AutoRegistrations { get; } = new List<ViewModelRegistration>();

public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
try
Expand All @@ -203,6 +226,7 @@ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
if (syntaxNode is ClassDeclarationSyntax classDeclarationSyntax)
{
var classAttribute = classDeclarationSyntax.AttributeLists.FirstOrDefault()?.Attributes.FirstOrDefault(attrib => (attrib.Name as IdentifierNameSyntax)?.Identifier.Text + "Attribute" == typeof(ApplicationServiceAttribute).Name);
var regAttribute = classDeclarationSyntax.AttributeLists.FirstOrDefault()?.Attributes.FirstOrDefault(attrib => (attrib.Name as IdentifierNameSyntax)?.Identifier.Text + "Attribute" == typeof(RegisterAttribute).Name);
if (classAttribute != null)
{
AppServiceTypeName = classDeclarationSyntax.Identifier.ValueText;
Expand All @@ -222,6 +246,26 @@ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
.FirstOrDefault() as IdentifierNameSyntax;
RegistrationPartialMethodName = identifier.Identifier.ValueText;

var secondArgument = classAttribute.ArgumentList.Arguments.Skip(1).FirstOrDefault();
identifier = secondArgument.Expression
.DescendantNodes()
.Where(x => x.Kind() == SyntaxKind.IdentifierName)
.Skip(1)
.FirstOrDefault() as IdentifierNameSyntax;
RegistrationServicesPartialMethodName = identifier.Identifier.ValueText;


}
else if (regAttribute != null)
{
var namespaceSyntax = classDeclarationSyntax.Parent as NamespaceDeclarationSyntax;
AutoRegistrations.Add(new ViewModelRegistration
{
ViewModelTypeName = classDeclarationSyntax.Identifier.ValueText,
ViewModelNamespace = namespaceSyntax.Name.ToString()

});

}
}

Expand All @@ -231,9 +275,10 @@ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
if (messageAttribute != null)
{
var eventName = eventDeclarationSyntax.Declaration.Variables.FirstOrDefault().Identifier.ValueText;
Registrations.Add(new EventRegistration() {
Registrations.Add(new EventRegistration()
{
EventSyntax = eventDeclarationSyntax,
EventName = eventName
EventName = eventName
});
//SemanticModel model = compilation.GetSemanticModel(syntaxTree);
//ISymbol symbol = model.GetSymbolInfo(syntaxNode).Symbol;
Expand All @@ -250,17 +295,26 @@ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
}
}
}
catch(Exception ex)
catch (Exception ex)
{

}
}



}

private class EventRegistration

private class ViewModelRegistration
{
public string ViewModelTypeName { get; set; }
public string ViewModelNamespace { get; set; }

}

private class EventRegistration : ViewModelRegistration
{
public string MessageTypeName { get; set; }
//public string MessageNamespace { get; set; }
public string EventName { get; set; }
Expand All @@ -269,6 +323,7 @@ private class EventRegistration
public string ParameterValueAsString { get; set; }

public EventFieldDeclarationSyntax EventSyntax { get; set; }

}
}
}
19 changes: 13 additions & 6 deletions BuildIt.Navigation/EventMessageAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
namespace BuildIt.Navigation
{
[AttributeUsage(AttributeTargets.Event)]
public class EventMessageAttribute:Attribute
public class EventMessageAttribute : Attribute
{
public Type MessageType { get; }
public Type MessageType { get; }

public Object MessageParameter { get; set; }

public EventMessageAttribute(Type messageType, object parameter=null)
public EventMessageAttribute(Type messageType, object parameter = null)
{
MessageType = messageType;
MessageParameter = parameter;
Expand All @@ -24,7 +24,7 @@ public class ViewModelAttribute : Attribute
public Type ViewModelType { get; }
public string InitMethodName { get; }

public ViewModelAttribute(Type viewModelType, string initMethod=null)
public ViewModelAttribute(Type viewModelType, string initMethod = null)
{
ViewModelType = viewModelType;
InitMethodName = initMethod;
Expand All @@ -34,11 +34,13 @@ public ViewModelAttribute(Type viewModelType, string initMethod=null)
[AttributeUsage(AttributeTargets.Class)]
public class ApplicationServiceAttribute : Attribute
{
public string RegistrationMethod { get; }
public string RegistrationMethod { get; }
public string RegistrationServicesMethod { get; }

public ApplicationServiceAttribute(string registrationMethod)
public ApplicationServiceAttribute(string registrationMethod, string serviceRegistrationMethod)
{
RegistrationMethod = registrationMethod;
RegistrationServicesMethod = serviceRegistrationMethod;
}
}

Expand All @@ -52,4 +54,9 @@ public ViewModelMappingRegisterAttribute(string registrationMethod)
RegistrationMappingMethod = registrationMethod;
}
}

[AttributeUsage(AttributeTargets.Class)]
public class RegisterAttribute : Attribute
{
}
}
33 changes: 8 additions & 25 deletions MvvmNavigation.Core/MvvmApplicationServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,21 @@ namespace MvvmNavigation



[ApplicationService(nameof(RegisterEvents))]
[ApplicationService(nameof(RegisterEvents), nameof(RegisterServices))]
public partial class MvvmApplicationServices:ApplicationService
{
partial void RegisterServices(IServiceCollection serviceRegistrations);
partial void RegisterEvents(NavigationEvents events);


protected override void InitializeApplicationServices(IServiceCollection serviceRegistrations)
{
base.InitializeApplicationServices(serviceRegistrations);

// HelloWorldGenerated.HelloWorld.SayHello();

serviceRegistrations.AddSingleton<INavigationEvents>(sp =>
{
var events = new NavigationEvents();
// Explicit creation of navigation message
//.Register<MainViewModel, EventHandler>
// ((v, a) => v.ViewModelDone += a, (v, a) => v.ViewModelDone -= a, (nav) => (s, ev) => nav(s.Complete(CompletionStates.One)));
// Implicit creation of completed navigation message
//.RegisterMessageWithParameter<MainViewModel, CompletedWithStatusMessage<CompletionStates>, CompletionStates>
// ((v, a) => v.ViewModelAlsoDone += a, (v, a) => v.ViewModelAlsoDone -= a, CompletionStates.Two);
//// Implicit creation of close navigation message
//.RegisterMessage<SecondViewModel, CloseMessage>
// ((v, a) => v.ViewModelDone += a, (v, a) => v.ViewModelDone -= a)
//// Explicit creation of close navigation message
//.Register<ThirdViewModel, EventHandler>
// ((v, a) => v.ViewModelDone += a, (v, a) => v.ViewModelDone -= a, (nav) => (s, ev) => nav(s.Close()));
RegisterEvents(events);
return events;
});

Expand Down Expand Up @@ -75,10 +56,12 @@ protected override void InitializeApplicationServices(IServiceCollection service
return routes;
});

serviceRegistrations.AddTransient<MainViewModel>();
serviceRegistrations.AddTransient<SecondViewModel>();
serviceRegistrations.AddTransient<ThirdViewModel>();
serviceRegistrations.AddTransient<FourthViewModel>();
//serviceRegistrations.AddTransient<MainViewModel>();
//serviceRegistrations.AddTransient<SecondViewModel>();
//serviceRegistrations.AddTransient<ThirdViewModel>();
//serviceRegistrations.AddTransient<FourthViewModel>();

RegisterServices(serviceRegistrations);
}
}

Expand Down
4 changes: 3 additions & 1 deletion MvvmNavigation.Core/ViewModels/FourthViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using Microsoft.Toolkit.Mvvm.ComponentModel;
using BuildIt.Navigation;
using Microsoft.Toolkit.Mvvm.ComponentModel;

namespace MvvmNavigation.ViewModels
{
[Register]
public class FourthViewModel : ObservableObject
{
public string Title { get; } = "Fourth Page - VM";
Expand Down
1 change: 1 addition & 0 deletions MvvmNavigation.Core/ViewModels/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace MvvmNavigation.ViewModels
{
[Register]
public class MainViewModel: ObservableObject
{

Expand Down
1 change: 1 addition & 0 deletions MvvmNavigation.Core/ViewModels/SecondViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

namespace MvvmNavigation.ViewModels
{
[Register]
public class SecondViewModel : ObservableObject
{
private int count;
Expand Down
1 change: 1 addition & 0 deletions MvvmNavigation.Core/ViewModels/ThirdViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace MvvmNavigation.ViewModels
{
[Register]
public class ThirdViewModel: ObservableObject
{
[EventMessage(typeof(CloseMessage))]
Expand Down

0 comments on commit d2e7ef1

Please sign in to comment.