EnumVisitorGenerator 1.1.2
dotnet add package EnumVisitorGenerator --version 1.1.2
NuGet\Install-Package EnumVisitorGenerator -Version 1.1.2
<PackageReference Include="EnumVisitorGenerator" Version="1.1.2"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="EnumVisitorGenerator" Version="1.1.2" />
<PackageReference Include="EnumVisitorGenerator"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add EnumVisitorGenerator --version 1.1.2
#r "nuget: EnumVisitorGenerator, 1.1.2"
#:package EnumVisitorGenerator@1.1.2
#addin nuget:?package=EnumVisitorGenerator&version=1.1.2
#tool nuget:?package=EnumVisitorGenerator&version=1.1.2
EnumVisitorGenerator
If you mark an enum with the [EnumVisitorGenerator.VisitorGenerator] attribute, the source generator will generate several "Visitor" interfaces, where each method will correspond to an item of the target enum. Additionally, an extension class with methods will be generated where the target enum is switched and corresponding visitor interface methods are called.
Installation
PM> NuGet\Install-Package EnumVisitorGenerator
Example
Target Enum
using EnumVisitorGenerator;
namespace SomeNamespace
{
[VisitorGenerator]
public enum Color
{
Red,
Green,
Blue
}
}
Generated Code
using System;
namespace SomeNamespace
{
public static class ColorEnumExtension
{
public static void Accept(this Color source, IColorVisitor visitor)
{
switch (source)
{
case Color.Red:
visitor.CaseRed();
break;
case Color.Green:
visitor.CaseGreen();
break;
case Color.Blue:
visitor.CaseBlue();
break;
default:
throw new ArgumentOutOfRangeException(nameof(source), source, null);
}
}
public static void Accept<TVisitor>(this Color source, ref TVisitor visitor)
where TVisitor : struct, IColorVisitor
{
switch (source)
{
case Color.Red:
visitor.CaseRed();
break;
case Color.Green:
visitor.CaseGreen();
break;
case Color.Blue:
visitor.CaseBlue();
break;
default:
throw new ArgumentOutOfRangeException(nameof(source), source, null);
}
}
public static T Accept<T>(this Color source, IColorVisitor<T> visitor)
{
switch (source)
{
case Color.Red:
return visitor.CaseRed();
case Color.Green:
return visitor.CaseGreen();
case Color.Blue:
return visitor.CaseBlue();
default:
throw new ArgumentOutOfRangeException(nameof(source), source, null);
}
}
public static T Accept<T, TVisitor>(this Color source, ref TVisitor visitor)
where TVisitor : struct, IColorVisitor<T>
{
switch (source)
{
case Color.Red:
return visitor.CaseRed();
case Color.Green:
return visitor.CaseGreen();
case Color.Blue:
return visitor.CaseBlue();
default:
throw new ArgumentOutOfRangeException(nameof(source), source, null);
}
}
public static T Accept<T, TArg>(this Color source, IColorVisitor<T, TArg> visitor, TArg arg)
{
switch (source)
{
case Color.Red:
return visitor.CaseRed(arg);
case Color.Green:
return visitor.CaseGreen(arg);
case Color.Blue:
return visitor.CaseBlue(arg);
default:
throw new ArgumentOutOfRangeException(nameof(source), source, null);
}
}
public static T Accept<T, TVisitor, TArg>(this Color source, ref TVisitor visitor, TArg arg)
where TVisitor : struct, IColorVisitor<T, TArg>
{
switch (source)
{
case Color.Red:
return visitor.CaseRed(arg);
case Color.Green:
return visitor.CaseGreen(arg);
case Color.Blue:
return visitor.CaseBlue(arg);
default:
throw new ArgumentOutOfRangeException(nameof(source), source, null);
}
}
}
public interface IColorVisitor
{
void CaseRed();
void CaseGreen();
void CaseBlue();
}
public interface IColorVisitor<out T>
{
T CaseRed();
T CaseGreen();
T CaseBlue();
}
public interface IColorVisitor<out T, in TArg>
{
T CaseRed(TArg arg);
T CaseGreen(TArg arg);
T CaseBlue(TArg arg);
}
}
Usage
class ColorTranslation : IColorVisitor<string, bool>
{
public string CaseRed(bool eng) => eng ? "Red" : "Rojo";
public string CaseGreen(bool eng) => eng ? "Green" : "Verde";
public string CaseBlue(bool eng) => eng ? "Blue" : "Azul";
}
...
var translation = new ColorTranslation();
Console.WriteLine(Color.Red.Accept(translation, false));
"Allocation Free" Usage
struct ColorTranslation : IColorVisitor<string, bool>
{
public string CaseRed(bool eng) => eng ? "Red" : "Rojo";
public string CaseGreen(bool eng) => eng ? "Green" : "Verde";
public string CaseBlue(bool eng) => eng ? "Blue" : "Azul";
}
...
var translation = new ColorTranslation();
//boxing does not happen here
Console.WriteLine(Color.Red.Accept<string, ColorTranslation, bool>(ref translation, false));
VisitorToMethod for Stateless Struct Visitors
You can generate a named extension wrapper from a stateless struct visitor:
[VisitorToMethod("GetColor")]
public struct VisitorStruct : IColorVisitor<string, bool>
{
public string CaseRed(bool eng) => eng ? "Red" : "Rojo";
public string CaseGreen(bool eng) => eng ? "Green" : "Verde";
public string CaseBlue(bool eng) => eng ? "Blue" : "Azul";
}
Generated in ColorEnumExtension:
public static string GetColor(this Color source, bool arg)
{
var visitor = new VisitorStruct();
return source.Accept<string, VisitorStruct, bool>(ref visitor, arg);
}
If your visitor is IColorVisitor<TResult> (without TArg), the generated method has no extra parameters and calls Accept<TResult, TVisitor>(ref visitor).
If TArg is a value tuple, it is flattened into multiple method parameters and re-packed for Accept.
You can find more details in this article.
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.