public override void GenerateFilterIl(ILGenerator generator, Dictionary<string, string> filterValues, PropertyInfo property) { Label lblReturnFalse = generator.DefineLabel(); Label lblNextProperty = generator.DefineLabel(); string minNumberString = filterValues["minNumber"]; string maxNumberString = filterValues["maxNumber"]; // If this is a nullable type such as bool?, the type is wrapped inside Nullable<> and we need to get the generic argument. string myPropertyType = IsNullable ? property.PropertyType.GetGenericArguments().Single().Name : property.PropertyType.Name; int storageIndex; switch (myPropertyType) { // Regardless of the width of the integer coming in, we treat it as a 64-bit integer. case "Byte": case "Int16": case "Int32": case "Int64": if (myPropertyType == "Byte") storageIndex = nullableByteStorage; else if (myPropertyType == "Int16") storageIndex = nullableInt16Storage; else if (myPropertyType == "Int32") storageIndex = nullableInt32Storage; else storageIndex = nullableInt64Storage; if (!string.IsNullOrWhiteSpace(minNumberString)) { generator.EmitCheckHasValue(property, storageIndex); generator.Emit(OpCodes.Brfalse, lblReturnFalse); // return false if the property is null // the integer from the record. generator.EmitGetValueFromNullableProperty(property, storageIndex); generator.Emit(OpCodes.Conv_I8); // convert to 64-bit integer // the minimum integer generator.Emit(OpCodes.Ldc_I8, Convert.ToInt64(minNumberString)); // If the integer is less than the minimum, return false. generator.Emit(OpCodes.Blt, lblReturnFalse); } if (!string.IsNullOrWhiteSpace(maxNumberString)) { generator.EmitCheckHasValue(property, storageIndex); generator.Emit(OpCodes.Brfalse, lblReturnFalse); // return false if the property is null // the integer from the record. generator.EmitGetValueFromNullableProperty(property, storageIndex); generator.Emit(OpCodes.Conv_I8); // convert to 64-bit integer // the maximum integer generator.Emit(OpCodes.Ldc_I8, Convert.ToInt64(maxNumberString)); // If the integer is greater than the maximum, return false. generator.Emit(OpCodes.Bgt, lblReturnFalse); } break; // Floating point types case "Single": case "Double": if (myPropertyType == "Single") storageIndex = nullableSingleStorage; else storageIndex = nullableDoubleStorage; if (!string.IsNullOrWhiteSpace(minNumberString)) { generator.EmitCheckHasValue(property, storageIndex); generator.Emit(OpCodes.Brfalse, lblReturnFalse); // return false if the integer is false // the number from the record. generator.EmitGetValueFromNullableProperty(property, storageIndex); generator.Emit(OpCodes.Conv_R8); // convert to 64-bit floating-point number // the minimum number generator.Emit(OpCodes.Ldc_R8, Convert.ToDouble(minNumberString)); // If the number is less than the minimum, return false. generator.Emit(OpCodes.Blt, lblReturnFalse); } if (!string.IsNullOrWhiteSpace(maxNumberString)) { generator.EmitCheckHasValue(property, storageIndex); generator.Emit(OpCodes.Brfalse, lblReturnFalse); // return false if the integer is false // the number from the record. generator.EmitGetValueFromNullableProperty(property, storageIndex); generator.Emit(OpCodes.Conv_R8); // convert to 64-bit floating-point number // the maximum number generator.Emit(OpCodes.Ldc_R8, Convert.ToDouble(maxNumberString)); // If the number is greater than the maximum, return false. generator.Emit(OpCodes.Bgt, lblReturnFalse); } break; // TODO: DECIMAL type } generator.Emit(OpCodes.Br, lblNextProperty); generator.MarkLabel(lblReturnFalse); generator.EmitReturnFalse(); generator.MarkLabel(lblNextProperty); }
public override void GenerateFilterIl(System.Reflection.Emit.ILGenerator generator, Dictionary <string, string> filterValues, PropertyInfo property) { string minDateString = filterValues["minDate"]; string maxDateString = filterValues["maxDate"]; bool isNullable = property.PropertyType.Name == "Nullable`1"; Label lblNextProperty = generator.DefineLabel(); Label lblReturnFalse = generator.DefineLabel(); // First, get the value loaded, but if it is null, then return false unless both minDate and maxDate are blank. if (isNullable) { // This block of code is so-far UNTESTED!!! MethodInfo GetNullableHasValue = typeof(DateTime?).GetProperty("HasValue").GetGetMethod(); MethodInfo GetNullableValue = typeof(DateTime?).GetProperty("Value").GetGetMethod(); bool minAndMaxBothBlank = string.IsNullOrWhiteSpace(minDateString) && string.IsNullOrWhiteSpace(maxDateString); Label whereToGoIfNull = minAndMaxBothBlank ? lblNextProperty : lblReturnFalse; // If the property is null and both min and max date are blank, then go to the next property. // If the property is null and either min or max date has a value, return false. generator.EmitGetPropertyValueFromArgument(property); generator.Emit(OpCodes.Stloc, nullableDateTimeStorage); generator.Emit(OpCodes.Ldloca_S, nullableDateTimeStorage); generator.Emit(OpCodes.Call, GetNullableHasValue); generator.Emit(OpCodes.Brfalse_S, whereToGoIfNull); // If we haven't jumped, then the datetime is not null, so just save it. generator.Emit(OpCodes.Ldloca_S, nullableDateTimeStorage); generator.Emit(OpCodes.Call, GetNullableValue); generator.Emit(OpCodes.Stloc, dateTimeStorage); } else // not nullable { // The property is not nullable, so just save the value. generator.EmitGetPropertyValueFromArgument(property); generator.Emit(OpCodes.Stloc, dateTimeStorage); } // At this point, the record's datetime should be saved in memory. MethodInfo DateTimeParse = typeof(DateTime).GetMethod("Parse", new Type[] { typeof(string) }); MethodInfo DateTimeLessThanOrEqual = typeof(DateTime).GetMethod("op_LessThanOrEqual"); MethodInfo DateTimeGreaterThanOrEqual = typeof(DateTime).GetMethod("op_GreaterThanOrEqual"); if (!string.IsNullOrWhiteSpace(minDateString)) { generator.Emit(OpCodes.Ldstr, minDateString); generator.Emit(OpCodes.Call, DateTimeParse); // Get the mindate DateTime. generator.Emit(OpCodes.Ldloc, dateTimeStorage); // Get the record's DateTime from memory generator.Emit(OpCodes.Call, DateTimeLessThanOrEqual); generator.Emit(OpCodes.Brfalse, lblReturnFalse); } if (!string.IsNullOrWhiteSpace(maxDateString)) { generator.Emit(OpCodes.Ldstr, maxDateString); generator.Emit(OpCodes.Call, DateTimeParse); // Get the maxdate DateTime. generator.Emit(OpCodes.Ldloc, dateTimeStorage); // Get the record's DateTime from memory generator.Emit(OpCodes.Call, DateTimeGreaterThanOrEqual); generator.Emit(OpCodes.Brfalse, lblReturnFalse); } generator.Emit(OpCodes.Br, lblNextProperty); generator.MarkLabel(lblReturnFalse); generator.EmitReturnFalse(); generator.MarkLabel(lblNextProperty); }
public override void GenerateFilterIl(System.Reflection.Emit.ILGenerator generator, Dictionary <string, string> filterValues, PropertyInfo property) { MethodInfo StringToLower = typeof(string).GetMethod("ToLower", new Type[] { }); MethodInfo StringStartsWith = typeof(String).GetMethod("StartsWith", new Type[] { typeof(string) }); MethodInfo StringContains = typeof(String).GetMethod("Contains", new Type[] { typeof(string) }); MethodInfo StringIsNullOrWhiteSpace = typeof(string).GetMethod("IsNullOrWhiteSpace", new Type[] { typeof(string) }); Label lblNextProperty = generator.DefineLabel(); Label lblNotNull = generator.DefineLabel(); string filterText = filterValues["filterText"]; string filterMode = filterValues["filterMode"]; // Do nothing for this property is the filterText is blank and the filterMode is "Starts With", "Doesn't Start With", "Contains", or " Doesn't Contain" if (string.IsNullOrWhiteSpace(filterText) && new string[] { "Starts With", "Doesn't Start With", "Contains", "Doesn't Contain" }.Contains(filterMode)) { return; } switch (filterMode) { case "Starts With": case "Contains": // Check that the property is not null. If it is null, return false; otherwise, continue. generator.EmitGetPropertyValueFromArgument(property); generator.Emit(OpCodes.Brtrue, lblNotNull); generator.EmitReturnFalse(); generator.MarkLabel(lblNotNull); // Load the property of the argument and make it lower-case. generator.EmitGetPropertyValueFromArgument(property); generator.Emit(OpCodes.Callvirt, StringToLower); // Load the lower-cased search key and see if the lower-cased property starts with it. generator.Emit(OpCodes.Ldstr, filterText.ToLower()); // We use either String.StartsWith or String.Contains according to what the user specified. generator.Emit(OpCodes.Callvirt, filterMode == "Starts With" ? StringStartsWith : StringContains); // If the search key doesn't match, then return false; otherwise, go on to the next property generator.Emit(OpCodes.Brtrue, lblNextProperty); generator.EmitReturnFalse(); break; case "Doesn't Start With": case "Doesn't Contain": // Check that the property is not null. If it is null, then go on to the next property. generator.EmitGetPropertyValueFromArgument(property); generator.Emit(OpCodes.Brfalse, lblNextProperty); // Load the property of the argument and make it lower-case. generator.EmitGetPropertyValueFromArgument(property); generator.Emit(OpCodes.Callvirt, StringToLower); // Load the lower-cased search key and see if the lower-cased property starts with it. generator.Emit(OpCodes.Ldstr, filterText.ToLower()); // We use either String.StartsWith or String.Contains according to what the user specified. generator.Emit(OpCodes.Callvirt, filterMode == "Starts With" ? StringStartsWith : StringContains); // Since we're doing the opposite of the "Starts With" and "Contains" cases, go to the next property // if the search key doesn't match, and return false otherwise. generator.Emit(OpCodes.Brfalse, lblNextProperty); generator.EmitReturnFalse(); break; case "Is Blank": // Load the property of the argument and see if it's null or whitespace generator.EmitGetPropertyValueFromArgument(property); generator.Emit(OpCodes.Call, StringIsNullOrWhiteSpace); // If we didn't get back true, then return false; otherwise, go on to the next property. generator.Emit(OpCodes.Brtrue, lblNextProperty); generator.EmitReturnFalse(); break; case "Isn't Blank": // Load the property of the argument and see if it's null or whitespace generator.EmitGetPropertyValueFromArgument(property); generator.Emit(OpCodes.Call, StringIsNullOrWhiteSpace); // If we didn't get back false, then return false; otherwise, go on to the next property. generator.Emit(OpCodes.Brfalse, lblNextProperty); generator.EmitReturnFalse(); break; } generator.MarkLabel(lblNextProperty); }
public override void GenerateFilterIl(ILGenerator generator, Dictionary<string, string> filterValues, PropertyInfo property) { // Note: If the user specifies both true and false, we can skip this instance string selection = filterValues["selection"]; string selectionLower = selection.ToLower(); bool selectionContainsTrue = selectionLower.Contains("true"); bool selectionContainsFalse = selectionLower.Contains("false"); bool selectionContainsNull = selectionLower.Contains("null"); Label lblReturnFalse = generator.DefineLabel(); Label lblCheckNextProperty = generator.DefineLabel(); generator.EmitCheckHasValue(property, nullableBoolStorage); // push 1 onto the stack if property has value; 0 if it is null. generator.Emit(OpCodes.Pop); // If the filter matches null, check if the value is null. if (selectionContainsNull) { generator.EmitCheckHasValue(property, nullableBoolStorage); generator.Emit(OpCodes.Brfalse, lblCheckNextProperty); } // If the property didn't match null and has no value, return false. generator.EmitCheckHasValue(property, nullableBoolStorage); generator.Emit(OpCodes.Brfalse, lblReturnFalse); // From here on out, we assume the property has a value. if (selectionContainsTrue) { generator.EmitGetValueFromNullableProperty(property, nullableBoolStorage); generator.Emit(OpCodes.Brtrue, lblCheckNextProperty); } if (selectionContainsFalse) { generator.EmitGetValueFromNullableProperty(property, nullableBoolStorage); generator.Emit(OpCodes.Brfalse, lblCheckNextProperty); } // If we've gotten this far without finding one of the values the user passed in, the record doesn't match, so return false. generator.MarkLabel(lblReturnFalse); generator.EmitReturnFalse(); generator.MarkLabel(lblCheckNextProperty); }