public void PickAllOneByOne() { var list = new List <int>(new int[] { 50, 51, 52, 53, 54 }); var picker = new ListElementPicker <int>(list); Assert.AreEqual(50, picker.Current); Assert.AreEqual(50, picker.Pick()); Assert.AreEqual(51, picker.Current); Assert.AreEqual(1, picker.CurrentIndex); Assert.AreEqual(0, picker.CurrentIndexOfUnpicked); Assert.IsTrue(picker.IsCurrentUnpicked()); Assert.AreEqual(51, picker.Pick()); Assert.AreEqual(52, picker.Current); Assert.AreEqual(2, picker.CurrentIndex); Assert.AreEqual(0, picker.CurrentIndexOfUnpicked); Assert.IsTrue(picker.IsCurrentUnpicked()); Assert.AreEqual(52, picker.Pick()); Assert.AreEqual(53, picker.Current); Assert.AreEqual(3, picker.CurrentIndex); Assert.AreEqual(0, picker.CurrentIndexOfUnpicked); Assert.IsTrue(picker.IsCurrentUnpicked()); Assert.AreEqual(53, picker.Pick()); Assert.AreEqual(54, picker.Current); Assert.AreEqual(4, picker.CurrentIndex); Assert.AreEqual(0, picker.CurrentIndexOfUnpicked); Assert.IsTrue(picker.IsCurrentUnpicked()); Assert.AreEqual(54, picker.Pick()); Assert.AreEqual(-1, picker.CurrentIndex); Assert.AreEqual(-1, picker.CurrentIndexOfUnpicked); Assert.IsFalse(picker.IsCurrentUnpicked()); }
internal static void InsertServiceInList(List <IService> list, IService service, bool forceReplace) { var allServices = new List <IService>(list); if (allServices.Select(s => s.ServiceType).Contains(service.ServiceType)) { // Service type already registered. So what now? int index = allServices.FindIndex(s => s.ServiceType == service.ServiceType); if (Object.ReferenceEquals(allServices[index], service)) { throw new Exception("Service already registered."); } if (forceReplace) { allServices[index] = service; } else { throw new Exception($"Service of the same service type already registered ({allServices[index].ServiceObject.GetType().FullName})."); } } else { allServices.Add(service); } var servicePicker = new ListElementPicker <IService>(allServices); var newList = new List <IService>(); int lastCount = -1; while (newList.Count != lastCount) { lastCount = newList.Count; foreach (var s in servicePicker.ListUnpicked()) { if (s.Dependencies.Count() == 0) { newList.Add(servicePicker.Pick()); } else { var allDepsFound = true; foreach (var d in s.Dependencies) { if (!newList.Exists(x => x.ServiceType == d)) { allDepsFound = false; break; } } if (allDepsFound) { newList.Add(servicePicker.Pick()); } } } } newList.AddRange(servicePicker.ListUnpicked()); // Insert those services with unresolved dependencies list.Clear(); list.AddRange(newList); }
internal int CheckMethodArguments( ref MethodInfo method, bool isProcedure, bool firstParIsThis, Expression instance, Expression contextReference, Expression extensionInstance, List <SBExpressionData> arguments, List <SBExpressionData> suggestedAssignmentsOut, PropertyBlock propertyBlock = null) { ListElementPicker <SBExpressionData> argPicker = new ListElementPicker <SBExpressionData>(arguments); ArgumentInsertState state = ArgumentInsertState.Initial; bool thisParameterHandled = false; int matchScore = 1000; if (isProcedure) { state = ArgumentInsertState.ProcedureContext; } else if (extensionInstance != null) { state = ArgumentInsertState.ExtensionInstance; } // Construct method if generic and extension method. if (method.IsGenericMethodDefinition && extensionInstance != null) { // NOTE: This has to be improved with checks to avoid mistakes. var t = extensionInstance.Type; if (extensionInstance.Type.IsConstructedGenericType) { t = t.GetGenericArguments()[0]; } method = method.MakeGenericMethod(t); } var parameters = method.GetParameters(); // Run through all the parameters; all must be assigned. for (int i = 0; i < parameters.Length; i++) { var p = parameters[i]; if (state == ArgumentInsertState.ExtensionInstance) { suggestedAssignmentsOut.Add(new SBExpressionData(extensionInstance)); state = ArgumentInsertState.Initial; continue; } else if (state == ArgumentInsertState.ProcedureContext) { suggestedAssignmentsOut.Add(new SBExpressionData(contextReference)); state = ArgumentInsertState.Initial; continue; } else if (state == ArgumentInsertState.Initial) { if (ImplicitAttribute.IsImplicit(p)) { if (p.ParameterType.IsAssignableFrom(typeof(ICallContext))) { if (isProcedure) { suggestedAssignmentsOut.Add(new SBExpressionData(m_currentProcedure.ContextReferenceInternal)); } else { suggestedAssignmentsOut.Add(new SBExpressionData(m_currentProcedure.ContextReference)); } continue; } else { // TODO: Parsing error. throw new NotImplementedException(); } } else if (!thisParameterHandled && firstParIsThis) { state = ArgumentInsertState.ThisReference; } else { state = ArgumentInsertState.Mandatory; } } if (state != ArgumentInsertState.ThisReference) { if (argPicker.UnpickedCount == 0 && state != ArgumentInsertState.ThisReference) { state = ArgumentInsertState.NoArguments; } else if (p.IsDefined(typeof(ParamArrayAttribute))) { state = ArgumentInsertState.Params; } } if (state == ArgumentInsertState.Mandatory) { if (p.GetType() == typeof(ArgumentList)) { state = ArgumentInsertState.ArgumentList; } else { if (argPicker.Current.IsNamed) { if (argPicker.AllBeforeCurrentArePickedAndOthersUnpicked()) { state = ArgumentInsertState.Named; } else { // TODO: report error; unexpected that args before current are not picked. return(0); } } else if (IsParameterAssignableFromArgument(p, argPicker.Current)) { var a = argPicker.Pick(); if (p.ParameterType == typeof(object)) { a = a.NewExpressionCode(Expression.Convert(a.ExpressionCode, typeof(object))); matchScore -= 10; // Matching an object parameter is not as good as matching the exact same type. } suggestedAssignmentsOut.Add(a); continue; // next parameter } else if (argPicker.Current.DataType.Type == typeof(Int64) && p.ParameterType.IsPrimitiveNarrowableIntType()) { suggestedAssignmentsOut.Add(new SBExpressionData(Expression.Convert(argPicker.Pick().ExpressionCode, p.ParameterType))); continue; // next parameter } else if (argPicker.Current.DataType.Type == typeof(Double) && p.ParameterType == typeof(Single)) { suggestedAssignmentsOut.Add(new SBExpressionData(Expression.Convert(argPicker.Pick().ExpressionCode, p.ParameterType))); matchScore -= 5; // Matching a 'single' is not as good as matching the exact same type. continue; // next parameter } else { state = ArgumentInsertState.Named; // Try finding the argument by name, then. } } } if (state == ArgumentInsertState.ThisReference) { thisParameterHandled = true; if (p.ParameterType.IsAssignableFrom(instance.Type)) { suggestedAssignmentsOut.Add(new SBExpressionData(instance)); state = ArgumentInsertState.Mandatory; // Not sure about this... } else { return(0); // Wrong type of 'this' reference } } if (state == ArgumentInsertState.Named) { // Note: Just because the call uses named arguments does not mean that the parameters have default values. if (argPicker.FindUnpicked(a => a.ParameterName == p.Name)) { suggestedAssignmentsOut.Add(argPicker.Pick()); continue; // next parameter } else { if (p.HasDefaultValue) { suggestedAssignmentsOut.Add( new SBExpressionData( Expression.Constant(p.DefaultValue, p.ParameterType))); continue; } else { // TODO: Report argument not found, maybe return(0); } } } if (state == ArgumentInsertState.Params) { if (!p.ParameterType.IsArray) { throw new Exception("Unexpected type of 'params' parameter; not an array."); } var t = p.ParameterType.GetElementType(); if (!argPicker.AllBeforeCurrentArePickedAndOthersUnpicked()) { // TODO: report error, maybe return(0); } if (argPicker.UnpickedCount == 1 && p.ParameterType.IsAssignableFrom(argPicker.Current.DataType.Type)) { suggestedAssignmentsOut.Add(argPicker.Pick()); continue; } else { var paramsArgs = new List <Expression>(); while (argPicker.UnpickedCount > 0) { if (t == argPicker.Current.DataType.Type) { paramsArgs.Add(argPicker.Pick().ExpressionCode); } else if (t.IsAssignableFrom(argPicker.Current.DataType.Type)) { paramsArgs.Add(Expression.Convert(argPicker.Pick().ExpressionCode, t)); } else { // TODO: report error, maybe return(0); } } suggestedAssignmentsOut.Add(new SBExpressionData(Expression.NewArrayInit(t, paramsArgs))); } continue; } if (state == ArgumentInsertState.NoArguments) { if (p.IsDefined(typeof(ParamArrayAttribute))) { if (!p.ParameterType.IsArray) { throw new Exception("Unexpected type of 'params' parameter; not an array."); } var t = p.ParameterType.GetElementType(); suggestedAssignmentsOut.Add(new SBExpressionData(Expression.NewArrayInit(t))); } else { if (p.HasDefaultValue) { object c = p.DefaultValue; if (c == null && p.ParameterType.IsValueType) { c = Activator.CreateInstance(p.ParameterType); } suggestedAssignmentsOut.Add( new SBExpressionData( Expression.Constant(c, p.ParameterType))); continue; } else { // TODO: Report argument not found, maybe return(0); } } } } if (suggestedAssignmentsOut.Count >= parameters.Length) { if (argPicker.PickedCount < arguments.Count) { throw new Exception("Not all passed arguments are used!"); // TODO: report in a better way. } return(matchScore); } return(0); }
public void PickAndSkip() { var list = new List <int>(new int[] { 50, 51, 52, 53, 54 }); var picker = new ListElementPicker <int>(list); Assert.AreEqual(50, picker.Current); Assert.IsTrue(picker.SkipToNextUnpicked()); // Don't pick, just skip to next. Assert.AreEqual(51, picker.Current); Assert.AreEqual(1, picker.CurrentIndex); Assert.AreEqual(1, picker.CurrentIndexOfUnpicked); Assert.IsTrue(picker.IsCurrentUnpicked()); Assert.AreEqual(51, picker.Pick()); Assert.AreEqual(52, picker.Current); Assert.AreEqual(2, picker.CurrentIndex); Assert.AreEqual(1, picker.CurrentIndexOfUnpicked); Assert.IsTrue(picker.IsCurrentUnpicked()); Assert.IsTrue(picker.SkipToNextUnpicked()); // Don't pick, just skip to next. Assert.AreEqual(53, picker.Current); Assert.AreEqual(3, picker.CurrentIndex); Assert.AreEqual(2, picker.CurrentIndexOfUnpicked); Assert.IsTrue(picker.IsCurrentUnpicked()); Assert.AreEqual(53, picker.Pick()); Assert.AreEqual(54, picker.Current); Assert.AreEqual(4, picker.CurrentIndex); Assert.AreEqual(2, picker.CurrentIndexOfUnpicked); Assert.IsTrue(picker.IsCurrentUnpicked()); Assert.IsTrue(picker.SelectFirstUnpicked()); Assert.AreEqual(50, picker.Current); Assert.AreEqual(0, picker.CurrentIndex); Assert.AreEqual(0, picker.CurrentIndexOfUnpicked); Assert.IsTrue(picker.IsCurrentUnpicked()); Assert.AreEqual(50, picker.Pick()); Assert.AreEqual(52, picker.Current); Assert.AreEqual(2, picker.CurrentIndex); Assert.AreEqual(0, picker.CurrentIndexOfUnpicked); Assert.IsTrue(picker.IsCurrentUnpicked()); Assert.AreEqual(52, picker.Pick()); Assert.AreEqual(54, picker.Current); Assert.AreEqual(4, picker.CurrentIndex); Assert.AreEqual(0, picker.CurrentIndexOfUnpicked); Assert.IsTrue(picker.IsCurrentUnpicked()); Assert.IsTrue(picker.SelectFirstUnpicked()); Assert.AreEqual(54, picker.Current); Assert.AreEqual(4, picker.CurrentIndex); Assert.AreEqual(0, picker.CurrentIndexOfUnpicked); Assert.IsTrue(picker.IsCurrentUnpicked()); Assert.AreEqual(54, picker.Pick()); // Pick last one Assert.AreEqual(-1, picker.CurrentIndex); Assert.AreEqual(-1, picker.CurrentIndexOfUnpicked); Assert.IsFalse(picker.IsCurrentUnpicked()); // All picked now. Assert.IsFalse(picker.SelectFirstUnpicked()); Assert.AreEqual(-1, picker.CurrentIndex); Assert.AreEqual(-1, picker.CurrentIndexOfUnpicked); Assert.IsFalse(picker.IsCurrentUnpicked()); }