This is a concrete case, implemented by the ASP.NET Web Api team on Github: https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Http/Results/OkResult.cs
I myself have applied the same pattern here.
Briefly, the above two links show a pattern variation "Parameter Object".
Public constructors of the class receive either their dependencies directly, or another object containing their dependencies.
Both public constructors involve the arguments in an instance of IDependencyProvider
, which is passed to a private constructor who extracts dependencies and treats them evenly. This constructor is considered a detail of implementation, customers do not need to know about it, and therefore it is 'private.
public class MyClass
{
private readonly string _dependency1;
private readonly string _dependency2;
public MyClass(string dependency1, int dependency2)
: this(new DirectDependencyProvider(dependency1, dependency2))
{
}
public MyClass(Container container)
: this(new ContainerDependencyProvider(container))
{
}
//constructor privado
private MyClass(IDependencyProvider provider)
{
_dependency1 = provider.Dependency1;
_dependency2 = provider.Dependency2;
//etc, fazer alguma coisa com as duas dependencias
}
private interface IDependencyProvider
{
string Dependency1 { get; }
int Dependency2 { get; }
}
private class DirectDependencyProvider : IDependencyProvider
{
private readonly string _dependency1;
private readonly int _dependency2;
public DirectDependencyProvider(string dependency1, int dependency2)
{
_dependency1 = dependency1;
_dependency2 = dependency2;
}
public string Dependency1
{
get { return _dependency1; }
}
public int Dependency2
{
get { return _dependency2; }
}
}
private class ContainerDependencyProvider : IDependencyProvider
{
private readonly Container _container;
public ContainerDependencyProvider(Container container)
{
if(container == null)
throw new ArgumentNullException("container");
_container = container;
}
public string Dependency1
{
get { return _container.StringStuff; }
}
public int Dependency2
{
get { return _container.IntStuff; }
}
}
}
Note that the interface IDependencyProvider
and its implementations are private types.
The alternative would be to use a private boot method, but we would have to sacrifice Fields readonly
and the guarantee of its immutability. This is a sacrifice that can and must be avoided.
public class MyClass
{
private string _dependency1;
private string _dependency2;
public MyClass(string dependency1, int dependency2)
{
Initialize(dependency1, dependency2);
}
public MyClass(Container container)
{
if(container == null)
throw new ArgumentNullException("container");
Initialize(container.StringStuff, container.IntStuff);
}
private void Initialize(string dependency1, int dependency2)
{
_dependency1 = dependency1;
_dependency2 = dependency2;
}
}
Only not useful for static classes declared as such because a class declared as static cannot be instantiated and can even have constructors, even if private.
– Caffé
@Caffé yes, of course.
– Maniero
@Caffé All classes have constructors, the constructors of static classes are more restrictive, but they exist. Read my answer to see an example.
– Malkaviano
@Malkavian Yes, I’ve even used this type of builder. But it has nothing to do with declaring a constructor as private in order to make it inaccessible - a static constructor even accepts access modifiers.
– Caffé