https://github.com/trympet/stronglytypeddictionarygenerator
Roslyn powered source generator for creating dictionaries backed by a strongly typed interface.
https://github.com/trympet/stronglytypeddictionarygenerator
component-model cross-platform csharp csharp-sourcegenerator roslyn source-generator
Last synced: 9 months ago
JSON representation
Roslyn powered source generator for creating dictionaries backed by a strongly typed interface.
- Host: GitHub
- URL: https://github.com/trympet/stronglytypeddictionarygenerator
- Owner: trympet
- License: mit
- Created: 2021-11-13T21:14:07.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2023-12-04T16:07:19.000Z (over 2 years ago)
- Last Synced: 2024-04-27T02:27:15.734Z (about 2 years ago)
- Topics: component-model, cross-platform, csharp, csharp-sourcegenerator, roslyn, source-generator
- Language: C#
- Homepage:
- Size: 52.7 KB
- Stars: 3
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# StronglyTypedDictionaryGenerator
Roslyn powered source generator for strongly typed dictionaries.
Easily turn an interface into a strongly typed dictionary. Use it for persisting data, interop, serialization, config files, etc.
## Generated source
#### Sample user defined input:
```csharp
interface IMyInterface
{
[System.ComponentModel.DefaultValue(69)]
int Property1 { get; set; }
bool Property2 { get; set; }
[System.ComponentModel.DefaultValue(true)]
bool Property3 { get; set; }
[System.ComponentModel.DefaultValue("Hello Roslyn!")]
string Property4 { get; set; }
CultureInfo Property5 { get; set; }
[System.ComponentModel.DefaultValue(null)]
TimeSpan Property6 { get; set; }
}
[StronglyTypedDictionary(targetType: typeof(IMyInterface), supportsDefaultValues: true)]
internal partial class MyStronglyTypedDictionary : IMyInterface
{
private bool someCondition;
protected override T GetOrDefault(T defaultValue, [CallerMemberName] string name = null!)
{
switch (name)
{
case nameof(IMyInterface.Property3) when someCondition:
defaultValue = (T)(object)false;
break;
default:
break;
}
return base.GetOrDefault(defaultValue, name);
}
public CultureInfo Property5
{
get => CultureInfo.GetCultureInfo(Get());
set => Set(value.Name);
}
}
```
#### Sample generated output:
```csharp
internal partial class MyStronglyTypedDictionary : GeneratedBase, global::Demo.IMyInterface
{
public MyStronglyTypedDictionary(IStronglyTypedKeyValuePairAccessor stronglyTypedKeyValuePairAccessor) : base(stronglyTypedKeyValuePairAccessor)
{
}
public MyStronglyTypedDictionary(global::System.Collections.Generic.IDictionary dictionary) : base(dictionary)
{
}
public int Property1
{
get => GetOrDefault(69);
set => Set(value);
}
public bool Property2
{
get => Get();
set => Set(value);
}
public bool Property3
{
get => GetOrDefault(true);
set => Set(value);
}
public string Property4
{
get => GetOrDefault("Hello Roslyn!");
set => Set(value);
}
public string Property6
{
get => GetOrDefault(default(System.TimeSpan));
set => Set(value);
}
}
public abstract class GeneratedBase
{
private sealed class StronglyTypedKvpWrapper : IStronglyTypedKeyValuePairAccessor
{
private readonly global::System.Collections.Generic.IDictionary dictionary;
public StronglyTypedKvpWrapper(global::System.Collections.Generic.IDictionary dictionary)
{
this.dictionary = dictionary;
}
public T Get(string name) where T : unmanaged
{
return (T)dictionary[name];
}
public string Get(string name)
{
return (string)dictionary[name];
}
public bool TryGet(string name, out T value) where T : unmanaged
{
var result = dictionary.TryGetValue(name, out object? v);
value = v is not null ? (T)v : default;
return result;
}
public bool TryGet(string name, [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out string? value)
{
var result = dictionary.TryGetValue(name, out object? v);
value = (string?)v;
return result;
}
public void Set(string name, T value) where T : unmanaged
{
dictionary[name] = value;
}
public void Set(string name, string value)
{
dictionary[name] = value;
}
}
private readonly IStronglyTypedKeyValuePairAccessor stronglyTypedKeyValuePairAccessor;
private protected GeneratedBase(IStronglyTypedKeyValuePairAccessor stronglyTypedKeyValuePairAccessor)
{
this.stronglyTypedKeyValuePairAccessor = stronglyTypedKeyValuePairAccessor;
}
private protected GeneratedBase(global::System.Collections.Generic.IDictionary dictionary)
: this(new StronglyTypedKvpWrapper(dictionary))
{
}
protected T Get([global::System.Runtime.CompilerServices.CallerMemberName] string name = null!) where T : unmanaged
{
return stronglyTypedKeyValuePairAccessor.Get(name);
}
protected string Get([global::System.Runtime.CompilerServices.CallerMemberName] string name = null!)
{
return stronglyTypedKeyValuePairAccessor.Get(name);
}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
protected virtual T GetOrDefault(T defaultValue, [global::System.Runtime.CompilerServices.CallerMemberName] string name = null!) where T : unmanaged
{
return stronglyTypedKeyValuePairAccessor.TryGet(name, out T result) ? result : defaultValue;
}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
protected virtual string GetOrDefault(string defaultValue, [global::System.Runtime.CompilerServices.CallerMemberName] string name = null!)
{
return stronglyTypedKeyValuePairAccessor.TryGet(name, out string? result) ? result : defaultValue;
}
protected void Set(T value, [global::System.Runtime.CompilerServices.CallerMemberName] string name = null!) where T : unmanaged
{
stronglyTypedKeyValuePairAccessor.Set(name, value);
}
protected void Set(string value, [global::System.Runtime.CompilerServices.CallerMemberName] string name = null!)
{
stronglyTypedKeyValuePairAccessor.Set(name, value);
}
}
public abstract class GeneratedBase : GeneratedBase
{
private protected GeneratedBase(IStronglyTypedKeyValuePairAccessor stronglyTypedKeyValuePairAccessor) : base(stronglyTypedKeyValuePairAccessor)
{
}
private protected GeneratedBase(global::System.Collections.Generic.IDictionary dictionary) : base(dictionary)
{
}
public TProperty Get(global::System.Linq.Expressions.Expression> expression)
where TProperty : unmanaged
{
return base.Get(GetMemberName(expression));
}
public string Get(global::System.Linq.Expressions.Expression> expression)
{
return base.Get(GetMemberName(expression));
}
public void Set(global::System.Linq.Expressions.Expression> expression, TProperty value)
where TProperty : unmanaged
{
base.Set(value, GetMemberName(expression));
}
public void Set(global::System.Linq.Expressions.Expression> expression, string value)
{
base.Set(value, GetMemberName(expression));
}
private static string GetMemberName(global::System.Linq.Expressions.Expression> expression)
{
return expression.Body switch
{
global::System.Linq.Expressions.MemberExpression m => m.Member.Name,
global::System.Linq.Expressions.UnaryExpression u when u.Operand is global::System.Linq.Expressions.MemberExpression m => m.Member.Name,
_ => throw new global::System.NotImplementedException($"Invalid expression: {expression.GetType()}. Exprected accessor."),
};
}
}
```