Good time of the day!
I have a generic interface which has a self-reference:
public interface IBuilder<TObject, TBuilder>
where TBuilder : IBuilder<TObject, TBuilder>
{
public TObject Build();
}
so I can use it like this:
public abstract class Builder<TObject, TBuilder> : IBuilder<TObject, TBuilder>
where TBuilder : Builder<TObject, TBuilder>
{
protected TObject obj;
protected readonly TBuilder @this;
protected abstract TObject CreateObject();
protected abstract void CheckBuildConstraints();
public Builder()
{
obj = CreateObject();
@this = (TBuilder)this;
}
public virtual TObject Build()
{
CheckBuildConstraints();
return obj;
}
}
public interface IContext
{
string Name { get; }
}
public interface IContextBuilder<TContext, TBuilder> : IBuilder<TContext, TBuilder>
where TContext : IContext
where TBuilder : IContextBuilder<TContext, TBuilder>
{
//...
TBuilder SetName(string name);
}
public class Context : IContext
{
public string Name => _name!;
protected string? _name;
protected Context() { }
public abstract class ContextBuilder<TContext, TBuilder>
: Builder<TContext, TBuilder>, IContextBuilder<TContext, TBuilder>
where TContext: Context
where TBuilder : ContextBuilder<TContext, TBuilder>
{
public ContextBuilder() : base() { }
protected override void CheckBuildConstraints()
{
obj._name ??= "default value";
}
//...
public TBuilder SetName(string name)
{
obj._name = name;
return @this;
}
}
public class ContextBuilder : ContextBuilder<Context, ContextBuilder>
{
public ContextBuilder() : base() { }
protected override Context CreateObject() => new();
}
}
and then do these FluentAPI-style chained calls:
var context = new Context.ContextBuilder().SetName("name").Build();
My questions are these:
- Do I overcomplicate things? Is there any simpler way to do what I did?
- How do I declare a variable of IContextBuilder<IContext, IContextBuilder<...>> type?
I have googled a lot of information and I have not been able to find anything usefull so far. I am hoping for your help. Cheers!