Skip to content

Instantly share code, notes, and snippets.

@thenameless314159
Created June 21, 2017 07:36
Show Gist options
  • Save thenameless314159/a5df5461f705c1bd2d981fb2afa16855 to your computer and use it in GitHub Desktop.
Save thenameless314159/a5df5461f705c1bd2d981fb2afa16855 to your computer and use it in GitHub Desktop.
Simple predicat/method wrapper
public class PartsManager<TP, T>
where TP : AbstractPart<T>
{
private static Dictionary<TP, MethodInfo> PartMapper { get; }
static PartsManager()
{
var ass = typeof(TP).Assembly;
var types =
ass.GetTypes()
.Where(
type => type.IsClass
&& !type.IsAbstract
&& type.IsAssignableFrom(typeof(TP)));
var parts = types.Select(type => (TP)Activator.CreateInstance(type)).ToImmutableList();
PartMapper = new Dictionary<TP, MethodInfo>(parts.Count);
foreach(var p in parts)
PartMapper.Add(p, p.GetType().GetMethods().First(mi => mi.Name != "Predicat"));
}
public void ExecuteParts(T input, IEnumerable<object> handlerParameters)
{
var haveParameters = CheckParameters(input, handlerParameters);
foreach (var pair in PartMapper)
{
var part = pair.Key;
var handlerMi = pair.Value;
// Invoke method cost is high, but this is only used for run-time expr generation
if (!part.Predicat(input)) continue;
if (haveParameters)
{
handlerMi.Invoke(part, new object[] { input });
break;
}
var newSize = handlerParameters.Count() + 1;
var newParamList = new List<object>(newSize) {input};
newParamList.AddRange(handlerParameters);
handlerMi.Invoke(part, newParamList.ToArray());
break;
}
}
private bool CheckParameters(T input, IEnumerable<object> handlerParameters)
{
Throw.IfNull(input, nameof(input));
var handlersParameters = PartMapper.First().Value.GetParameters();
if (!handlerParameters.Any())
return false;
return PartMapper.All(pair =>
pair.Value.GetParametersType().SequenceEqual(handlerParameters.Select(hp => hp.GetType())));
}
}
public abstract class AbstractPart<T>
{
public abstract bool Predicat(T param);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment