I have the following class which represents my activity.
using System;
using System.Activities;
using System.Reflection;
namespace Tafs.Activities.Parsing
{
public class TryParse : CodeActivity<bool>
{
public InArgument<Type> OutputType { get; set; }
public InArgument<string> InputString { get; set; }
public OutArgument<object> ParseResult { get; set; }
protected override bool Execute(CodeActivityContext context)
{
Type type = OutputType.Get(context);
var parseInputMethod = GetType().GetMethod(nameof(TryParse.ParseInput), BindingFlags.NonPublic | BindingFlags.Instance).MakeGenericMethod(type);
return (bool)parseInputMethod.Invoke(this, new[] { context });
}
private bool ParseInput<T>(CodeActivityContext context)
{
string input = InputString.Get(context);
if (Parser.GetParser<T>().Value is IParser<T> parser)
{
if (parser.TryParse(input, out T result))
{
ParseResult.Set(context, result);
return true;
}
}
return false;
}
}
}
This works pretty well, but I’d like to make some improvements.
Is it possible to have the type of ParseResult
change to match the type selected in OutputType
? I’m looking for this to function similarly to the System.Activities.Statements.Switch
activity, where there is a type selector and choosing a different type selector replaces the activity with a string switch or an int switch or whatever the case may be.
End goal is I would like to avoid people having to manually cast back to the preferred type so as to emulate T.TryParse()
as closely as possible.
Also, I’m working on figuring out a way to expand beyond the existing set of parsers. I’ve built a parser for each of C# types that have a TryParse method, but if you have a type that exists in a third party library, you’re SOL.
I do have these methods I built into my parsing library for further expansion later so I may build into that a bit.
/// <summary>
/// Registers a new parser or overwrites an existing parser for the specified type.
/// </summary>
/// <typeparam name="T">The type to provide a parser for</typeparam>
/// <param name="parser">The parser for this type.</param>
public static void SetParser<T>(IParser<T> parser) => TypeParsers[typeof(T)] = parser;
/// <summary>
/// Unregisters a specified type and its parser.
/// </summary>
/// <typeparam name="T">The type to unregister.</typeparam>
/// <returns>True if a value is removed; otherwise, false.</returns>
public static bool UnsetParser<T>() => TypeParsers.Remove(typeof(T));
/// <summary>
/// Unregisters a specified type and its parser.
/// </summary>
/// <param name="type">The type ot unregister.</param>
/// <returns>True if a value is removed; otherwise, false.</returns>
public static bool UnsetParser(Type type) => TypeParsers.Remove(type);```