Skip to content

Instantly share code, notes, and snippets.

@MarkPflug
Created May 23, 2024 21:54
Show Gist options
  • Save MarkPflug/7623e42781fde59357c41d835046b61c to your computer and use it in GitHub Desktop.
Save MarkPflug/7623e42781fde59357c41d835046b61c to your computer and use it in GitHub Desktop.
Generic Specialization for IParsable<T>
using System.Reflection;
var x = GetParser<Thing>();
var y = GetParser<int>();
static IParser<T> GetParser<T>()
{
// specialize for T == Thing
if (typeof(T) == typeof(Thing))
{
if (MyThingParser.Inst is IParser<T> p)
{
return p;
}
}
// maybe more specializations of T
// if (typeof(T) == typeof(...))
// handle any generic IParsable<T>
var p2 = TryGetGenericParser<T>();
return p2;
}
static IParser<T> TryGetGenericParser<T>()
{
// dynamically specialize T for IParsable<T> via reflection
var ifaces = typeof(T).FindInterfaces(TypeFilter, typeof(T));
if (ifaces.Length == 1)
{
var i = ifaces[0];
var t = typeof(GenericParser<>).MakeGenericType(i.GetGenericArguments()[0]);
var f = BindingFlags.Static | BindingFlags.Public;
var v = t.GetField("Inst", f).GetValue(null) as IParser<T>;
return v;
}
return null;
}
static bool TypeFilter(Type type, object o)
{
var p = (Type)o;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IParsable<>) && type.GetGenericArguments()[0] == p)
return true;
return false;
}
interface IParser<T>
{
T Parser(string s);
}
class Thing
{
public static readonly Thing A = new Thing();
public static readonly Thing B = new Thing();
}
// custom parser I don't own "Thing", so can't apply IParsable<T>
class MyThingParser : IParser<Thing>
{
public static MyThingParser Inst = new MyThingParser();
public Thing Parser(string s)
{
return string.IsNullOrEmpty(s) ? Thing.A : Thing.B;
}
}
// generic parser for any IParsable<T> type.
class GenericParser<T> : IParser<T> where T : IParsable<T>
{
public static readonly GenericParser<T> Inst = new GenericParser<T>();
public T Parser(string s)
{
return T.Parse(s, null);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment