Create a gist now

Instantly share code, notes, and snippets.

Configurable polymorphic fluent interface in C#
using System;
using System.Collections.Generic;
namespace ConfigurablePolymorphicFluentInterface
{
public class Program
{
static void Main(string[] args)
{
string s = ListEnrollmentsSelectBuilder.Create()
.Data()
.HistoryOn(new DateTime(2016, 6, 1))
.Course(x => x.Data().HistoryInRange(new DateTime(2016, 5, 1), new DateTime(2016, 6, 1)))
.Domain()
.User(x => x.Session().Data().AllHistory())
.Metrics(x => x.AllHistory());
Console.WriteLine(s);
string t = ListEnrollmentsSelectBuilder.Create()
.Data()
.Domain()
.AllHistory()
.HistoryOn(new DateTime(2014, 3, 2))
.HistoryInRange(new DateTime(2015, 1, 2), new DateTime(2015, 1, 6))
.Course(x => x.Data()
.AllHistory()
.HistoryOn(new DateTime(2014, 3, 2))
.HistoryInRange(new DateTime(2015, 1, 2), new DateTime(2015, 1, 6)))
.User(x => x.Data()
.Session()
.AllHistory()
.HistoryOn(new DateTime(2014, 3, 2))
.HistoryInRange(new DateTime(2015, 1, 2), new DateTime(2015, 1, 6)))
.Metrics(x => x.AllHistory()
.HistoryOn(new DateTime(2014, 3, 2))
.HistoryInRange(new DateTime(2015, 1, 2), new DateTime(2015, 1, 6)));
Console.WriteLine(t);
}
}
public class SelectBuilder
{
public List<string> SelectItems { get; }
public SelectBuilder()
{
SelectItems = new List<string>();
}
public string Build()
{
return string.Join(",", SelectItems);
}
internal void AddSubBuilder<TSelectBuilder>(Action<TSelectBuilder> action)
where TSelectBuilder : SelectBuilder, new()
{
var selectBuilder = new TSelectBuilder();
action(selectBuilder);
SelectItems.AddRange(selectBuilder.SelectItems);
}
public static implicit operator string(SelectBuilder d)
{
return d.Build();
}
}
public class SelectBuilder<T> : SelectBuilder
{
public static SelectBuilder<T> Create()
{
return new SelectBuilder<T>();
}
}
public class ListEnrollmentsSelectBuilder : SelectBuilder<ListEnrollmentsSelectBuilder>,
IWithData,
IWithDomain,
IWithHistory,
IWithCourse,
IWithCourseBuilder, IWithCourseData, IWithCourseHistory,
IWithUser,
IWithUserBuilder,
IWithUserData, IWithUserHistory, IWithUserSession,
IWithMetrics,
IWithMetricsBuilder, IWithMetricsHistory
{
}
public class ListCoursesSelectBuilder : SelectBuilder<ListCoursesSelectBuilder>,
IWithData,
IWithHistory,
IWithDomain,
IWithDomainBuilder, IWithDomainData,
IWithBase,
IWithBaseBuilder, IWithBaseData,
IWithEnrollmentMetrics
{
}
public class DomainSelectBuilder<T> : SelectBuilder { }
public class CourseSelectBuilder<T> : SelectBuilder { }
public class UserSelectBuilder<T> : SelectBuilder { }
public class BaseSelectBuilder<T> : SelectBuilder { }
public class MetricsSelectBuilder<T> : SelectBuilder { }
public interface IWithData { }
public interface IWithDomain { }
public interface IWithDomainBuilder { }
public interface IWithDomainData { }
public interface IWithCourse { }
public interface IWithCourseBuilder { }
public interface IWithCourseData { }
public interface IWithCourseHistory { }
public interface IWithHistory { }
public interface IWithEnrollmentMetrics { }
public interface IWithMetrics { }
public interface IWithMetricsBuilder { }
public interface IWithMetricsHistory { }
public interface IWithUser { }
public interface IWithUserBuilder { }
public interface IWithUserData { }
public interface IWithUserSession { }
public interface IWithUserHistory { }
public interface IWithBase { }
public interface IWithBaseBuilder { }
public interface IWithBaseData { }
public static class SelectBuilderExtensions
{
public static SelectBuilder<T> Data<T>(this SelectBuilder<T> builder) where T : IWithData
{
builder.SelectItems.Add("data");
return builder;
}
public static SelectBuilder<T> Course<T>(this SelectBuilder<T> builder) where T : IWithCourse
{
builder.SelectItems.Add("course");
return builder;
}
public static SelectBuilder<T> Course<T>(this SelectBuilder<T> builder, Action<CourseSelectBuilder<T>> action) where T : IWithCourseBuilder
{
builder.SelectItems.Add("course");
builder.AddSubBuilder(action);
return builder;
}
public static SelectBuilder<T> Domain<T>(this SelectBuilder<T> builder) where T : IWithDomain
{
builder.SelectItems.Add("domain");
return builder;
}
public static SelectBuilder<T> Domain<T>(this SelectBuilder<T> builder, Action<DomainSelectBuilder<T>> action) where T : IWithDomainBuilder
{
builder.SelectItems.Add("domain");
builder.AddSubBuilder(action);
return builder;
}
public static SelectBuilder<T> User<T>(this SelectBuilder<T> builder) where T : IWithUser
{
builder.SelectItems.Add("user");
return builder;
}
public static SelectBuilder<T> User<T>(this SelectBuilder<T> builder, Action<UserSelectBuilder<T>> action) where T : IWithUserBuilder
{
builder.SelectItems.Add("user");
builder.AddSubBuilder(action);
return builder;
}
public static SelectBuilder<T> Base<T>(this SelectBuilder<T> builder) where T : IWithBase
{
builder.SelectItems.Add("base");
return builder;
}
public static SelectBuilder<T> Base<T>(this SelectBuilder<T> builder, Action<BaseSelectBuilder<T>> action) where T : IWithBaseBuilder
{
builder.SelectItems.Add("base");
builder.AddSubBuilder(action);
return builder;
}
public static SelectBuilder<T> EnrollmentMetrics<T>(this SelectBuilder<T> builder) where T : IWithEnrollmentMetrics
{
builder.SelectItems.Add("enrollmentmetrics");
return builder;
}
public static SelectBuilder<T> Metrics<T>(this SelectBuilder<T> builder) where T : IWithMetrics
{
builder.SelectItems.Add("metrics");
return builder;
}
public static SelectBuilder<T> Metrics<T>(this SelectBuilder<T> builder, Action<MetricsSelectBuilder<T>> action) where T : IWithMetricsBuilder
{
builder.SelectItems.Add("metrics");
builder.AddSubBuilder(action);
return builder;
}
public static SelectBuilder<T> AllHistory<T>(this SelectBuilder<T> builder) where T : IWithHistory
{
builder.SelectItems.Add("history(all)");
return builder;
}
public static SelectBuilder<T> HistoryOn<T>(this SelectBuilder<T> builder, DateTime date) where T : IWithHistory
{
builder.SelectItems.Add($"history(on,{date.SelectFormat()})");
return builder;
}
public static SelectBuilder<T> HistoryInRange<T>(this SelectBuilder<T> builder, DateTime from, DateTime to) where T : IWithHistory
{
builder.SelectItems.Add($"history(range,{from.SelectFormat()}{to.SelectFormat()})");
return builder;
}
}
public static class DomainSelectBuilderExtensions
{
public static DomainSelectBuilder<T> Data<T>(this DomainSelectBuilder<T> builder) where T : IWithDomainData
{
builder.SelectItems.Add("domain.data");
return builder;
}
}
public static class BaseSelectBuilderExtensions
{
public static BaseSelectBuilder<T> Data<T>(this BaseSelectBuilder<T> builder) where T : IWithBaseData
{
builder.SelectItems.Add("base.data");
return builder;
}
}
public static class CourseSelectBuilderExtensions
{
public static CourseSelectBuilder<T> Data<T>(this CourseSelectBuilder<T> builder) where T : IWithCourseData
{
builder.SelectItems.Add("course.data");
return builder;
}
public static CourseSelectBuilder<T> AllHistory<T>(this CourseSelectBuilder<T> builder) where T : IWithCourseHistory
{
builder.SelectItems.Add("course.history(all)");
return builder;
}
public static CourseSelectBuilder<T> HistoryOn<T>(this CourseSelectBuilder<T> builder, DateTime date) where T : IWithCourseHistory
{
builder.SelectItems.Add($"course.history(on,{date.SelectFormat()})");
return builder;
}
public static CourseSelectBuilder<T> HistoryInRange<T>(this CourseSelectBuilder<T> builder, DateTime from, DateTime to) where T : IWithCourseHistory
{
builder.SelectItems.Add($"course.history(range,{from.SelectFormat()},{to.SelectFormat()})");
return builder;
}
}
public static class MetricsSelectBuilderExtensions
{
public static MetricsSelectBuilder<T> AllHistory<T>(this MetricsSelectBuilder<T> builder) where T : IWithCourseHistory
{
builder.SelectItems.Add("metrics.history(all)");
return builder;
}
public static MetricsSelectBuilder<T> HistoryOn<T>(this MetricsSelectBuilder<T> builder, DateTime date) where T : IWithCourseHistory
{
builder.SelectItems.Add($"metrics.history(on,{date.SelectFormat()})");
return builder;
}
public static MetricsSelectBuilder<T> HistoryInRange<T>(this MetricsSelectBuilder<T> builder, DateTime from, DateTime to) where T : IWithCourseHistory
{
builder.SelectItems.Add($"metrics.history(range,{from.SelectFormat()},{to.SelectFormat()})");
return builder;
}
}
public static class UserSelectBuilderExtensions
{
public static UserSelectBuilder<T> Data<T>(this UserSelectBuilder<T> builder) where T : IWithUserData
{
builder.SelectItems.Add("user.data");
return builder;
}
public static UserSelectBuilder<T> Session<T>(this UserSelectBuilder<T> builder) where T : IWithUserSession
{
builder.SelectItems.Add("user.session");
return builder;
}
public static UserSelectBuilder<T> AllHistory<T>(this UserSelectBuilder<T> builder) where T : IWithUserHistory
{
builder.SelectItems.Add("user.history(all)");
return builder;
}
public static UserSelectBuilder<T> HistoryOn<T>(this UserSelectBuilder<T> builder, DateTime date) where T : IWithUserHistory
{
builder.SelectItems.Add($"user.history(on,{date.SelectFormat()})");
return builder;
}
public static UserSelectBuilder<T> HistoryInRange<T>(this UserSelectBuilder<T> builder, DateTime from, DateTime to) where T : IWithUserHistory
{
builder.SelectItems.Add($"user.history(range,{from.SelectFormat()},{to.SelectFormat()})");
return builder;
}
}
public static class DateTimeExtensions
{
public static string SelectFormat(this DateTime dateTime)
{
return dateTime.ToString("s") + "Z";
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment