I'm trying to create a Fluent API that describes a nested structure and as a result I would like to use generics to type the resulting object. I would like to do something like:
var test = new Query<Entity>().Select(x => x.UniqueValue<string>())
.Select(x => x.UniqueValue<DateTime>())
.Select(x => x.UniqueValue<decimal>());
Where test would be of type:
Result<Entity, string, Result<Entity, DateTime, Result<Entity, decimal>>>
So far I have code like:
class Program
{
static void Main(string[] args)
{
// test : ResultWithResult<Entity,string, Result<Entity, DateTime, ChildLessResult<Entity, decimal>>>
var test = new Query<Entity>().Select(x => x.UniqueValue<string>())
.Select(x => x.UniqueValue<DateTime>())
.Select(x => x.UniqueValue<decimal>());
}
}
public class Entity
{
public string Item1 { get; set; }
}
public class Aggregate<TEntity>
{
public ChildLessResult<TEntity, TReturnValue> UniqueValue<TReturnValue>()
{
return new ChildLessResult<TEntity, TReturnValue>();
}
}
public class Query<TEntity>
{
public ChildLessResult<TEntity, TReturnValue> Select<TReturnValue>(Func<Aggregate<TEntity>, ChildLessResult<TEntity, TReturnValue>> predicate)
{
var aggregator = new Aggregate<TEntity>();
return predicate(aggregator);
}
}
public class ChildLessResult<TEntity, TReturnValue>
{
public Result<TEntity, TReturnValue, TChild> Select<TChild>(Func<Aggregate<TEntity>, ChildLessResult<TEntity, TChild>> predicate)
{
return new Result<TEntity, TReturnValue, TChild>();
}
}
public class Result<TEntity, TReturnValue, TChild>
{
private ChildLessResult<TEntity, TChild> _child = new ChildLessResult<TEntity, TChild>();
public ResultWithResult<TEntity, TReturnValue, Result<TEntity, TChild, ChildLessResult<TEntity, TNewChild>>> Select<TNewChild>(Func<Aggregate<TEntity>, ChildLessResult<TEntity, TNewChild>> predicate)
{
return new ResultWithResult<TEntity, TReturnValue,
Result<TEntity, TChild, ChildLessResult<TEntity, TNewChild>>>();
}
}
public class ResultWithResult<TEntity, TReturnValue, TChild>
{
}
As you can see this is pretty limited since it only allows you to go as deep as the structures you have defined and you would need a new structure for each level deeper. Is it possible to create types that would allow an unlimited number of levels (i.e. as many Selects as you would ever want without the same corresponding number of Types).