Very usefull in ressource aggregation, here you will find a code snippet that can be integrated in Inversion Of Control pattern using Interface Segregation Principle of SOLID designing principles.
public interface IBinder
{
}
public interface IBinder<in T> : IBinder
{
void Bind(IEnumerable<T> bounds);
}
public interface IBinderDirector<T>
{
IBinder<T>[] DataBinders { get; }
void Bind(IEnumerable<T> bounds);
void BindParallel(IEnumerable<T> bounds);
void BindOnlySelected(IEnumerable<T> bounds, IEnumerable<Type> selecteds);
void BindAllExcept(IEnumerable<T> bounds,IEnumerable<Type> excepts);
void BindOnlySelectedParallel(IEnumerable<T> bounds,IEnumerable<Type> selecteds);
void BindAllExceptParallel(IEnumerable<T> bounds,IEnumerable<Type> excepts);
}
public class BinderDirector<T> : IBinderDirector<T>
{
private readonly IBinder<T>[] _dataBinders;
public IBinder<T>[] DataBinders => throw new NotImplementedException();
public BinderDirector(IEnumerable<IBinder<T>> dataBinders)
{
_dataBinders = (dataBinders ?? Enumerable.Empty<IBinder<T>>()).ToArray();
}
public void Bind(IEnumerable<T> bounds)
{
var boundAsList = bounds.ToArray();
foreach(var dataBinder in _dataBinders) dataBinder.Bind(boundAsList);
}
public void BindAllExcept(IEnumerable<T> bounds, IEnumerable<Type> excepts)
{
var boundArray = bounds.ToArray();
var runnableDataBinders = _dataBinders.Where(m => excepts.Any(s => !s.IsAssignableFrom(m.GetType())));
foreach (var dataBinder in runnableDataBinders) dataBinder.Bind(bounds);
}
public void BindAllExceptParallel(IEnumerable<T> bounds, IEnumerable<Type> excepts)
{
var boundArray = bounds.ToArray();
var runnableDataBinders = _dataBinders.Where(m => excepts.Any(s => !s.IsAssignableFrom(m.GetType())));
Parallel.ForEach(runnableDataBinders, (runnableDataBinder, index) => runnableDataBinder.Bind(bounds));
}
public void BindOnlySelected(IEnumerable<T> bounds, IEnumerable<Type> selecteds)
{
var boundArray = bounds.ToArray();
var runnableDataBinders = _dataBinders.Where(m => selecteds.Any(s => s.IsAssignableFrom(m.GetType())));
foreach (var dataBinder in runnableDataBinders) dataBinder.Bind(bounds);
}
public void BindOnlySelectedParallel(IEnumerable<T> bounds, IEnumerable<Type> selecteds)
{
var boundArray = bounds.ToArray();
var runnableDataBinders = _dataBinders.Where(m => selecteds.Any(s => s.IsAssignableFrom(m.GetType())));
Parallel.ForEach(runnableDataBinders, (runnableDataBinder, index) => runnableDataBinder.Bind(bounds));
}
public void BindParallel(IEnumerable<T> bounds)
{
var boundArray = bounds.ToArray();
Parallel.ForEach(_dataBinders, dataBinder => dataBinder.Bind(boundArray));
}
}
Underneath you will find an example of concrete implementation. The thing which is interesant, is that the BinderDirector is a pure interpretation of the Interface Segregation Principle :
public interface IWithBindPropertiesA
{
string IdentifierA { get; }
string ReturnedPropertyValueA { set; }
}
public interface IWithBindPropertiesB
{
string IdentifierB { get; }
string ReturnedPropertyValueB { set; }
}
public class ConcreteImplementation : IWithBindPropertiesA, IWithBindPropertiesB
{
public new string IdentifierA { get; set; }
public new string ReturnedPropertyValueA { get; set; }
public new string IdentifierB { get; set; }
public new string ReturnedPropertyValueB { get; set; }
}
public class BindPropertiesABinder : IBinder<IWithBindPropertiesA>
{
public void Bind(IEnumerable<IWithBindPropertiesA> bounds)
{
foreach(var bound in bounds)
{
bound.ReturnedPropertyValueA = bound.IdentifierA == "A"?"A":"unknown"; //In fact you can do what you want
}
}
}
public class BindPropertiesBBinder : IBinder<IWithBindPropertiesB>
{
public void Bind(IEnumerable<IWithBindPropertiesB> bounds)
{
foreach (var bound in bounds)
{
bound.ReturnedPropertyValueB = bound.IdentifierB == "B" ? "B" : "unknown"; //In fact you can do what you want
}
}
}
public static class Program
{
public static void Main(string[] argc)
{
var binderDirector = new BinderDirector<ConcreteImplementation>(new IBinder<ConcreteImplementation>[] {
new BindPropertiesABinder(),
new BindPropertiesBBinder()
});
}
}