Created
July 21, 2016 00:31
-
-
Save bdrupieski/30438b0f4356f77610234c3d8f41cf73 to your computer and use it in GitHub Desktop.
Configurable polymorphic fluent interface in C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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