using System.Collections.Generic;
public static void Main()
var s = new ScheduleCalculator();
s.Calculate(new ModelA());
s.Calculate(new ModelB());
public class ScheduleCalculator
private static Dictionary<string, Type> registeredTypes = new Dictionary<string, Type>();
static ScheduleCalculator()
registeredTypes.Add(nameof(ModelA), typeof(ConcreteA));
registeredTypes.Add(nameof(ModelB), typeof(ConcreteB));
public object Calculate<T>(T item) where T : ModelBase
var instance = CreateGeneric<T>();
return instance.Method(item);
private static IBase<T> CreateGeneric<T>() where T : ModelBase
if (!registeredTypes.ContainsKey(t))
throw new NotSupportedException();
var typeToCreate = registeredTypes[t];
return Activator.CreateInstance(typeToCreate, true) as IBase<T>;
internal interface IBase<in T> where T : ModelBase
internal abstract class Base<T> : IBase<T> where T : ModelBase
public object Method(T item)
return InternalMethod(item);
protected abstract object InternalMethod(T item);
internal class ConcreteA : Base<ModelA>
protected override object InternalMethod(ModelA item)
Console.WriteLine("Internal A");
internal class ConcreteB : Base<ModelB>
protected override object InternalMethod(ModelB item)
Console.WriteLine("Internal B");
public class ModelA : ModelBase
public class ModelB : ModelBase