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); }
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); }