tags:

views:

68

answers:

1

Hi All!

Assuming there are following interfaces

public interface IRoot
{
  IChildA ChildA { get; }
  IChildB ChildB { get; }
}  
public interface IChildA
{
  IGrandChildA GrandChildA { get; }
  IGrandChildB GrandChildB { get; }
}
public interface IChildB
{
  IGrandChildC GrandChildC { get; }
}
public interface IGrandChildA
{
}
public interface IGrandChildB
{
}
public interface IGrandChildC
{
}

I would like to write fluent-style 'configurator' in order to keep interface associations. Everything should look like this:

private static void Test()
{
  Configurator.Root<IRoot>()
    .Join( _ => _.ChildA )
    .Join( _ => _.GrandChildA )
    .Up()
    .Join( _ => _.GrandChildB )
    .Up()
    .Up()
    .Join( _ => _.ChildB );
}

It is required to allow arbitrary nesting level of Join/Up pairs. Here is my attempt to declare such configurator.

public static class Configurator
{
  public static IConfigBuilder<T, T> Root<T>()
  {
    return null;
  }
}
public interface IConfigBuilder<P, T>
{
  IConfigBuilder<T, C> Join<C>( Expression<Func<T, C>> expression );
  IConfigBuilder<???, P> Up(); // This is the problem. How can I get grand-parent type?
}

It is unclear for me how I could remember all preceding nodes types. In other words, how to declare Up() method? This reminds me old good Alexandrescu's type lists in C++. Is there any way to achieve the same in .net?

+1  A: 

You would need at least two interfaces; and rather than return IConfigBuilder<...> for Up, trust the creating code to know what it created:

public interface IConfigBuilder<T>
{
    IConfigBuilder<IConfigBuilder<T>, C> Join<C>(Expression<Func<T, C>> expression);
}
public interface IConfigBuilder<P, T> : IConfigBuilder<T>
{
    P Up(); // This is the problem. How can I get grand-parent type?
    new IConfigBuilder<IConfigBuilder<P, T>, C> Join<C>(Expression<Func<T, C>> expression);
}
Marc Gravell