Skip to content

Commit

Permalink
Optimized IocPage following benchmarks.
Browse files Browse the repository at this point in the history
  • Loading branch information
Simnico99 committed Sep 16, 2022
1 parent 3208c1b commit bc1a2b7
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 116 deletions.
35 changes: 1 addition & 34 deletions src/ZirconNet.Core/Runtime/DynamicClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,7 @@ public sealed class DynamicClass : DynamicObject
{
private readonly Dictionary<string, KeyValuePair<Type, object?>> _fields;

public DynamicClass(List<DynamicClassField> fields)
{
_fields = new Dictionary<string, KeyValuePair<Type, object?>>();
foreach (var field in fields)
{
try
{
var first = _fields.Single(x => x.Key == field.FieldName);
}
catch (Exception ex) when (ex is ArgumentNullException or InvalidOperationException)
{
_fields.Add(field.FieldName, new KeyValuePair<Type, object?>(field.FieldType, field.Value));
}
}
}

public DynamicClass(DynamicClassField[] fields)
public DynamicClass(IEnumerable<DynamicClassField> fields)
{
_fields = new Dictionary<string, KeyValuePair<Type, object?>>();
foreach (var field in fields)
Expand Down Expand Up @@ -49,21 +33,4 @@ public override bool TryGetMember(GetMemberBinder binder, out object? result)
result = _fields[binder.Name].Value;
return true;
}
public void SetFieldValue(string fieldName, object value)
{
var currentField = _fields.FirstOrDefault(x => x.Key == fieldName);
if (value.GetType() == currentField.Value.Key)
{
var newValue = new KeyValuePair<Type, object?>(currentField.Value.Key, value);
var key = _fields.Where(pair => pair.Key == fieldName)
.Select(pair => pair.Key)
.FirstOrDefault();
if (key is not null)
{
_fields[key] = newValue;
}
return;
}
throw new ArgumentException($"{value} type ({value?.GetType()}) is not the same as the Field ({currentField.Value.Key})", nameof(value));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,11 @@
[AttributeUsage(AttributeTargets.Class)]
public sealed class PageDataContextAttribute : Attribute
{
public Type[]? PagesToBindType { get; }
public Type[] PagesToBindType { get; } = Array.Empty<Type>();
public PageDataContextAttribute() { }

public PageDataContextAttribute(params Type[] pagesToBind)
{
if (pagesToBind?.Length < 0 || pagesToBind is null)
{
return;
}
PagesToBindType = pagesToBind;
}
}
85 changes: 8 additions & 77 deletions src/ZirconNet.WPF/Mvvm/IocPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,67 +10,11 @@ public class IocPage : Page
{
public IocPage(IServiceProvider servicesProvider, IServiceCollection services)
{
var currentDataContexts = GetPageDataContexts(servicesProvider, services);
var i = 0;
#if NET5_0_OR_GREATER
var fields = new DynamicClassField[currentDataContexts.Count];
foreach (var dataContext in CollectionsMarshal.AsSpan<ViewModel>(currentDataContexts))
{
var contextType = dataContext.GetType();
fields[i++] = new DynamicClassField(contextType.Name, contextType, dataContext);
}
#else
var fields = new DynamicClassField[currentDataContexts.Count()];
foreach (var dataContext in currentDataContexts)
{
var contextType = dataContext.GetType();
fields[i++] = new DynamicClassField(contextType.Name, contextType, dataContext);
}
#endif

var dynamicClass = new DynamicClass(fields);
var dynamicClass = new DynamicClass(GetPageDataContexts(servicesProvider, services));
DataContext = dynamicClass;
}

#if NET5_0_OR_GREATER
private List<ViewModel> GetPageDataContexts(IServiceProvider servicesProvider, IServiceCollection services)
{
var viewModels = new List<ViewModel>();

foreach (var service in CollectionsMarshal.AsSpan(services.ToList()))
{
if (!service.ServiceType.IsSameOrSubclassOf(typeof(ViewModel)))
{
continue;
}

var viewModel = (ViewModel?)servicesProvider.GetService(service.ServiceType);
var attribute = viewModel?.GetType().GetCustomAttribute<PageDataContextAttribute>();

if (attribute is not (not null and PageDataContextAttribute pageDataContextAttribute))
{
continue;
}

if (viewModel is null)
{
continue;
}

if (pageDataContextAttribute.PagesToBindType is null)
{
viewModels.Add(viewModel);
continue;
}
if (pageDataContextAttribute.PagesToBindType.Contains(GetType()))
{
viewModels.Add(viewModel);
}
}

return viewModels;
#else
private IEnumerable<ViewModel> GetPageDataContexts(IServiceProvider servicesProvider, IServiceCollection services)
private IEnumerable<DynamicClassField> GetPageDataContexts(IServiceProvider servicesProvider, IServiceCollection services)
{
foreach (var service in services)
{
Expand All @@ -79,33 +23,20 @@ private IEnumerable<ViewModel> GetPageDataContexts(IServiceProvider servicesProv
continue;
}

var viewModel = (ViewModel?)servicesProvider.GetService(service.ServiceType);
var attribute = viewModel?.GetType().GetCustomAttribute<PageDataContextAttribute>();

if (attribute is not (not null and PageDataContextAttribute pageDataContextAttribute))
{
continue;
}
var viewModel = (ViewModel)servicesProvider.GetRequiredService(service.ServiceType);
var viewModelType = viewModel.GetType();
var attribute = viewModelType.GetCustomAttribute<PageDataContextAttribute>();

if (viewModel is null)
if (attribute is not (not null and PageDataContextAttribute pageDataContextAttribute) || viewModel is null)
{
continue;
}

if (pageDataContextAttribute.PagesToBindType is null)
if (pageDataContextAttribute.PagesToBindType.Length <= 0 || pageDataContextAttribute.PagesToBindType.Contains(GetType()))
{
yield return viewModel;
yield return new DynamicClassField(viewModelType.Name, viewModelType, viewModel);
continue;
}
foreach (var type in pageDataContextAttribute.PagesToBindType)
{
if (type == GetType())
{
yield return viewModel;
continue;
}
}
}
#endif
}
}

0 comments on commit bc1a2b7

Please sign in to comment.