Skip to content

Commit

Permalink
Added support for mapping to Dictionary<T, Action<TArg>>
Browse files Browse the repository at this point in the history
  • Loading branch information
almostchristian committed Mar 25, 2023
1 parent 68daf4e commit cc750b3
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,22 @@
// Copyright (c) almostchristian. All rights reserved.
// -------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using ConfigurationProcessor.Core.Assemblies;
using Microsoft.Extensions.Configuration;
using ConfigLookup = System.ValueTuple<ConfigurationProcessor.Core.Implementation.TypeResolver[], Microsoft.Extensions.Configuration.IConfigurationSection, System.Collections.Generic.Dictionary<string, (ConfigurationProcessor.Core.Implementation.IConfigurationArgumentValue ArgName, Microsoft.Extensions.Configuration.IConfigurationSection ConfigSection)>>;

namespace ConfigurationProcessor.Core.Implementation
{
internal abstract class ConfigurationReader
{
private readonly IConfigurationSection section;
private readonly AssemblyFinder assemblyFinder;
private readonly ResolutionContext resolutionContext;

protected ConfigurationReader(
ResolutionContext resolutionContext,
IConfiguration rootConfiguration,
AssemblyFinder assemblyFinder,
IConfigurationSection configSection)
{
this.resolutionContext = resolutionContext;
this.assemblyFinder = assemblyFinder;
this.section = configSection;
RootConfiguration = rootConfiguration;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal class ConfigurationReader<TConfig> : ConfigurationReader, IConfiguratio
where TConfig : class
{
public ConfigurationReader(IConfiguration configuration, IConfigurationSection configSection, AssemblyFinder assemblyFinder, ConfigurationReaderOptions options)
: base(new ResolutionContext(assemblyFinder, configuration, configSection, options.AdditionalMethods, options.OnExtensionMethodNotFound, null, typeof(TConfig)), configuration, assemblyFinder, configSection)
: base(new ResolutionContext(assemblyFinder, configuration, configSection, options.AdditionalMethods, options.OnExtensionMethodNotFound, null, typeof(TConfig)), configuration, configSection)
{
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Configuration;
Expand Down Expand Up @@ -87,6 +88,20 @@ public StringArgumentValue(IConfigurationSection section, string providedValue,
throw new FormatException("Invalid conversion from numeric to TimeSpan. Only strings are allowed.");
}

// if the requested type is a single paramter Action and the value is True, we map it to a blank function
if (toTypeInfo.IsGenericType && toTypeInfo.GetGenericTypeDefinition() == typeof(Action<>) && bool.TryParse(argumentValue, out var boolvalue))
{
if (boolvalue)
{
var param = Expression.Parameter(toTypeInfo.GenericTypeArguments[0]);
return Expression.Lambda(Expression.Empty(), param).Compile();
}
else
{
return null;
}
}

if ((toTypeInfo.IsInterface || toTypeInfo.IsAbstract || typeof(Delegate).IsAssignableFrom(toType) || typeof(MethodInfo) == toType) && !string.IsNullOrWhiteSpace(argumentValue))
{
// check if value looks like a static property or field directive
Expand Down
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</PropertyGroup>

<PropertyGroup>
<Version>1.10.1</Version>
<Version>1.11.0</Version>
<FileVersion>$(Version).$([System.DateTime]::Now.ToString(yy))$([System.DateTime]::Now.DayOfYear.ToString(000))</FileVersion>
<PackageVersion>$(Version)</PackageVersion>
<InformationalVersion>$(FileVersion)-$(GIT_VERSION)</InformationalVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.ComponentModel;
using System.Reflection;
using TestDummies;
using static ConfigurationProcessor.DependencyInjection.UnitTests.Support.Extensions;

Expand Down Expand Up @@ -292,6 +290,41 @@ public void WithObjectNotation_MapTypeDictionaryUsingObjectNotation_RegistersSer
sd => Assert.Equal(typeof(Dictionary<Type, Type>), sd.ServiceType));
}

[Fact]
public void WithObjectNotation_MapTypeActionDictionaryUsingObjectNotation_RegistersService()
{
var json = @$"
{{
'DummyTypeActionMap': {{
'{NameOf<DummyTestClass>()}': true,
'{NameOf<DummyDelegate>()}': {{}},
'{NameOf<DummyParameter>()}': {{
'PropertyA': 42,
'PropertyB': 'hello',
'PropertyC': false,
'AppendString': 'abcd'
}}
}}
}}";

var serviceCollection = ProcessJson(json);

var sp = serviceCollection.BuildServiceProvider();
var map = sp.GetService<Dictionary<Type, Action<SimpleObject>>>();
Assert.NotNull(map);
Action<SimpleObject> action;
Assert.True(map.TryGetValue(typeof(DummyTestClass), out action));
Assert.NotNull(action);
Assert.True(map.TryGetValue(typeof(DummyDelegate), out action));
Assert.Null(action);
Assert.True(map.TryGetValue(typeof(DummyParameter), out action));
Assert.NotNull(action);
var simpleObject = new SimpleObject();
action(simpleObject);
Assert.Equal(42, simpleObject.PropertyA);
Assert.Equal("helloabcd", simpleObject.PropertyB);
}

[Fact]
public void WithObjectNotation_MapTypeDictionaryDirectly_RegistersService()
{
Expand Down
12 changes: 12 additions & 0 deletions tests/TestDummies/DummyServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,18 @@ public static IServiceCollection AddDummyTypeMap(this IServiceCollection service
return services;
}

public static IServiceCollection AddDummyTypeActionMap(this IServiceCollection services, Dictionary<Type, Action<SimpleObject>> configurations)
{
services.AddSingleton(configurations);
return services;
}

public static SimpleObject AppendString(this SimpleObject value, string toAppend)
{
value.PropertyB += toAppend;
return value;
}

public static IServiceCollection AddDummyStringMap(this IServiceCollection services, Dictionary<string, string> mappings)
{
services.AddSingleton(mappings);
Expand Down

0 comments on commit cc750b3

Please sign in to comment.