using System.Collections.Generic;
using System.Runtime.CompilerServices;
public interface INotification
Severity Severity { get; set; }
string Message { get; set; }
public string SeverityName
return Severity.ToString().ToLower();
public class Notification : INotification
public Severity Severity { get; set; }
public string Message { get; set; }
public class NotificationWithOverride : INotification
public Severity Severity { get; set; }
public string Message { get; set; }
public string SeverityName => Severity.ToString().ToLower();
public class NotificationWithOverrideAndBaseCall : INotification
static Func<INotification, string> GetBaseSeverity =
(Func<INotification, string>)
Delegate.CreateDelegate(typeof(Func<INotification, string>), null, typeof(INotification).GetProperty(nameof(INotification.SeverityName)).GetGetMethod());
public Severity Severity { get; set; }
public string Message { get; set; }
public string SeverityName => GetBaseSeverity(this);
public static class TypeExtension
public static MethodInfo[] GetExtensionMethods(this Type t, Assembly assembly = null)
var assemblies = assembly == null ? AppDomain.CurrentDomain.GetAssemblies() : new [] { assembly };
var query = from a in assemblies
from type in a.GetTypes()
where type.IsSealed && !type.IsGenericType && !type.IsNested
from method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
where method.IsDefined(typeof(ExtensionAttribute), false)
where method.GetParameters()[0].ParameterType == t
return query.ToArray<MethodInfo>();
public static MethodInfo GetExtensionMethod(this Type t, string MethodeName, Assembly assembly = null)
var mi = from methode in t.GetExtensionMethods(assembly)
where methode.Name == MethodeName
if (mi.Count<MethodInfo>() <= 0)
return mi.First<MethodInfo>();
static void Main(string[] args)
Console.WriteLine("\nProperties of {0}: [{1}]", typeof(INotification), string.Join(", ", typeof(INotification).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Select(p => p.Name)));
Console.WriteLine("Methods of {0}: [{1}]", typeof(INotification), string.Join(", ", typeof(INotification).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Select(p => p.Name)));
Console.WriteLine("Extension methods of {0}: [{1}]", nameof(INotification.SeverityName), string.Join(", ", typeof(INotification).GetExtensionMethods(typeof(INotification).Assembly).Select(m => m.Name)));
Console.WriteLine("{0}.{1} method type name: {2}", nameof(INotification), nameof(INotification.SeverityName), typeof(INotification).GetProperty(nameof(INotification.SeverityName)).GetGetMethod().GetType().FullName);
Test<NotificationWithOverride>();
Test<NotificationWithOverrideAndBaseCall>();
static void TestNonGeneric()
var notification = new Notification
notification.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Select(p => p.Name).ToArray().Dump();
Console.WriteLine(((INotification)notification).SeverityName);
var jsonText = JsonSerializer.Serialize(notification);
Console.WriteLine(jsonText);
static void Test<TNotification>() where TNotification : INotification, new()
Console.WriteLine("\nTesting {0}:", typeof(TNotification));
var notification = new TNotification
Console.WriteLine("Properties of {0}: {1}", typeof(TNotification), string.Join(", ", notification.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Select(p => p.Name)));
Console.WriteLine("Methods of {0}: {1}", typeof(TNotification), string.Join(", ", notification.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Select(p => p.Name)));
ShowInterfaceMapping(typeof(INotification), typeof(TNotification));
Console.WriteLine("{0} = {1}", nameof(INotification.SeverityName), notification.SeverityName);
var jsonText = JsonSerializer.Serialize(notification);
Console.WriteLine(jsonText);
Console.WriteLine("Result from Json.NET:");
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(notification));
private static void ShowInterfaceMapping(Type intType, Type implType)
InterfaceMapping map = implType.GetInterfaceMap(intType);
Console.WriteLine("Mapping of {0} to {1}: ", map.InterfaceType, map.TargetType);
for (int ctr = 0; ctr < map.InterfaceMethods.Length; ctr++) {
MethodInfo im = map.InterfaceMethods[ctr];
MethodInfo tm = map.TargetMethods[ctr];
Console.WriteLine(" {0} --> {1} ({2})", im.Name,tm.Name, tm.ReflectedType);