I'm somewhat confused by the warning I'm getting. Here is the relevant code:
#nullable enable
public partial class FileTable<TItem> : ComponentBase, IDisposable
{
// bunch of class code
public async Task FilterColumn(Func<TItem, IComparable>? itemProperty, string? searchString)
{
ArgumentNullException.ThrowIfNull(ViewItems);
if (itemProperty == null)
return;
if (searchString == null)
searchString = string.Empty;
await Task.Run(() =>
{
foreach (var item in ViewItems)
{
var property = itemProperty(item.Item);
if (property == null)
continue;
item.IsVisible = property.ToString().ToLower().Contains(searchString.ToLower());
}
});
StateHasChanged();
}
}
I'm getting the warning for property.ToString() As you can see I have already added a bunch of null-checks, but none seems to get rid of the warning. As far as I can see it is impossible for property to be null at the this point. Obviously I'm missing something...so what could be triggering this warning?
The problem is that ToString() can return null; it is bad practice, but: it can:
namespace System
{
public class Object
{
// ...
public virtual string? ToString();
// ...
}
}
the error goes away if you rule that out:
var s = property.ToString() ?? "";
item.IsVisible = s.ToLower().Contains(searchString.ToLower());
Note also that it is more efficient to use a comparison that ignores case, rather than forcing additional string allocations:
item.IsVisible = s.Contains(searchString, StringComparison.CurrentCultureIgnoreCase);
Related
I have a few items -- let's just call them itemA, itemB, itemC, and itemD -- and I would like to validate each of them using a validation method I have written.
The validation method return type and signature is as follows:
public async Task<ValidationMessage> ValidateItem(MyClass item);
The ValidationMessage is a simple class:
public class ValidationMessage
{
public bool Success { get; set; }
public string ErrorMessage { get; set; }
}
To validate each item, currently I have the following code:
ValidationMessage result = new ValidationMessage();
result = await this.ValidateItem(itemA);
if (!result.Success)
{
return result;
}
result = await this.ValidateItem(itemB);
if (!result.Success)
{
return result;
}
result = await this.ValidateItem(itemC);
if (!result.Success)
{
return result;
}
result = await this.ValidateItem(itemD);
return result;
As you can see, as soon as one of the items fails the validation method (meaning result.Success == false), I return and do not continue with validating the rest of them.
I think it's kind of tedious/ugly to have the repeated assignments to result and the repeated if statements. I was hoping there is some existing c# class/construct (perhaps LINQ can help) to write this more concisely. I made up the following to demonstrate what I'm sort of thinking:
ValidationMessage result = new ValidationMessage();
result = await this.ValidateItem(itemA).ContinueConditional(
(r => r.Success) => await this.ValidateItem(itemB).ContinueConditional(
(r => r.Success) => await this.ValidateItem(itemC).ContinueConditional(
(r => r.Success) => await this.ValidateItem(itemD))));
return result;
Basically, the return value of this.ValidateItem(itemA) is assigned to result and then this value goes into the ContinueConditional. If the result, r, has Success == true, then continue with validating itemB, and so on. If it's not successful, then exit out of that code and go straight to the return statement at the bottom, thus returning the item which failed the validation. If all items are validated then it will go to that return statement anyway.
I apologize for the long wall of text, especially if the c# construct already exists and is obvious. I appreciate any help with this.
Note: I have simplified my real example for the sake of posting this. One important part of the simplification is that itemA, itemB, itemC, and itemD are not the same type, despite referring to them as MyClass in the method signature above. So I can't just put them in a list and use LINQ. This also means I actually have different validation methods to accept the various items I have, but I didn't want to explain all that at the top in case it over-complicates things. The important part is that they all return ValidationMessage.
What about inverting the logic around the check for success/failure?
ValidationMessage result = await this.ValidateItem(itemA);
if (result.Success) result = await this.ValidateItem(itemB);
if (result.Success) result = await this.ValidateItem(itemC);
if (result.Success) result = await this.ValidateItem(itemD);
return result;
How about this? You can extend it to as many elements as you want.
var validationRules = new List<Func<Task<bool>>>(){
() => ValidateItem(itemA),
() => ValidateItem(itemB),
() => ValidateItem(itemC),
() => ValidateItem(itemD),
};
ValidationMessage result = new ValidationMessage();
foreach(var validationRule in validationRules)
{
result = await validationRule();
if(!result)
return result;
}
return result;
You could use FluentValidation to create a custom rule to loop through a list of models to validate. This is more overhead than the other answers but it's a good approach with clean readable code.
First define your shared model
public class YourSharedModel()
{
List<MyClass> Models = new List<MyClass>();
}
Define the validator:
public class SharedModelValidator : AbstractValidator<YourSharedModel>
{
public SharedModelValidator()
{
CustomRule(BeValid)
}
public bool BeValid(ValidationErrors<YourSharedModel> validationFailures, YourSharedModel sharedModel, ValidationContext<YourSharedModel> validationContext)
{
for (var m in sharedModel.Models)
{
var result = YourValidationMethod(m);
if (!result.Success)
{
validationFailures.AddFailureFor(x => m, result.ErrorMessage);
return false;
}
}
return true;
}
private YourValidationMethod(MyClass model)
{
// the code you have that actually validates
}
}
Implementation would be something like:
var yourSharedModel = new YourSharedModel();
yourSharedModel.Models.Add(itemA);
yourSharedModel.Models.Add(itemB);
// etc
var validator = new SharedModelValidator();
var results = validator.Validate(yourSharedModel);
if (!results.IsValid)
{
// do something with results.Errors
}
You could also keep all your errors and return false after the loop so that you get all the errors at once rather than one by one on submission, of course that's assuming a form post from a web application. Makes for a better user friendly experience.
You could use an interface and then add your items to a list that you foreach through:
ValidationMessage Test()
{
List<IValidatable> items = new List<IValidatable>();
MyClass1 item1 = new MyClass1();
MyClass2 item2 = new MyClass2();
items.Add(item1);
items.Add(item2);
ValidationMessage result = null;
foreach (var i in items)
{
result = i.ValidateItem();
if (!result.Success) break;
}
return result;
}
interface IValidatable
{
ValidationMessage ValidateItem();
}
public class ValidationMessage
{
public bool Success { get; set; }
public string ErrorMessage { get; set; }
}
public class MyClass1 : IValidatable
{
public ValidationMessage ValidateItem()
{
return new ValidationMessage();
}
}
public class MyClass2 : IValidatable
{
public ValidationMessage ValidateItem()
{
return new ValidationMessage();
}
}
Another (perhaps anorthodox) way to do it is to overload the && operator on ValidationMessage:
public class ValidationMessage
{
public bool Success { get; set; }
public string ErrorMessage { get; set; }
public static ValidationMessage operator &(ValidationMessage message1, ValidationMessage message2)
{
return message1.Success ? message2 : message1;
}
public static ValidationMessage operator |(ValidationMessage message1, ValidationMessage message2)
{
return message1.Success ? message1 : message2;
}
public static bool operator true(ValidationMessage message)
{
return message.Success;
}
public static bool operator false(ValidationMessage message)
{
return !message.Success;
}
}
Then you can do:
return (await this.ValidateItem(ItemA)) &&
(await this.ValidateItem(ItemB)) &&
(await this.ValidateItem(ItemC)) &&
(await this.ValidateItem(ItemD));
So I have a boolean method that is used to verify if a command is valid. This is used inside of an engine in which it verifies that the process can continue or not. This is the validation method:
private bool CommandIsValid(WC command)
{
if (command.Address == null ||
command.UserId < 0 ||
String.IsNullOrEmpty(command.CurrencyCode) ||
command.Amount < .01m ||
command.Address.PrimitiveAddress == null ||
String.IsNullOrEmpty(command.Address.Source) ||
String.IsNullOrEmpty(command.Address.PrimitiveAddress.City) ||
String.IsNullOrEmpty(command.Address.PrimitiveAddress.Country) ||
String.IsNullOrEmpty(command.Address.PrimitiveAddress.FirstName) ||
String.IsNullOrEmpty(command.Address.PrimitiveAddress.LastName) ||
String.IsNullOrEmpty(command.Address.PrimitiveAddress.Region) ||
command.Address.Created <= DateTime.MinValue)
{
return false;
}
return true;
}
And is called here inside of my method here:
if (!CommandIsValid(cmd))
{
_logger.Debug("Invalid command);
}
The issue is that I want to have some type of information regarding what failed validation. The best solution would have a list of what validations didn't pass, so I could relay that in my logging debugger. Obviously I could do this using a bunch of if-else statements, but it seems sloppy, as having a bunch of if else statements seems very poor style and I was wondering if there is any way in c# or in general I can do to avoid this.
Are you familiar with DataAnnotations and it's associated Validator class?
It would require modifications to your object.
public PrimitiveAddress
{
[Required]
public string City {get;set;}
}
and then you use it like so:
var context = new ValidationContext(command.Address.PrimitiveAddress);
var results = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(recipe, context, results);
if (!isValid)
{
foreach (var validationResult in results)
{
Console.WriteLine(validationResult.ErrorMessage);
}
}
if you've got a base command class you could probably add it in a more generic fashion. You can create your own validation attributes, use IValidatableObject for anything complex, customize the error messages
[Required(ErrorMessage="This is required.")]
Instead of returning a bool, return a container of bool values where first is the overall status False/True then each one reflects a condition of the above. If first element is False, then you check which condition (index) is the false. Looks like it is fixed in size then you may just agree on the sequence.
Something like this:
List<bool> YourFunction(YourDebuggerThing Input)
{
List<bool> Result = new List<bool>();
if (Input.Condition1 == false || Input.Condition2 == false || Input.Condition3 == false || Input.Condition4 == false || Input.Condition5 == false)
Result.Add(false); // first element is always the overall status
if(Input.Condition1 == false) Result.Add(false); else Result.Add(true); // element 2 is condition 1
if(Input.Condition2 == false) Result.Add(false); else Result.Add(true); // element 3 is condition 2
// ..
// ConditionN
return Result;
}
One idea might be to implement your checks within the Get/Set methods of the class' properties, using a custom exception. Such as;
public class PrimitiveAddresses
{
private string _city;
public string City
{
get
{
if(_city != null) {return _city;}
else {throw new CommandInvalidException("No valid city provided");}
}
set
{
_city = value;
}
}
}
public class CommandInvalidException: Exception
{
public CommandInvalidException(string message)
: base(message)
{
}
}
Then during you implementation, use a try/catch to handle the specific error;
public void foo()
{
try
{
if (String.IsNullOrEmpty(command.Address.PrimitiveAddress.City)){} // Ect
}
catch (CommandInvalidException e)
{
Console.WriteLine("Command invalid due to " + e.message);
// Or any other way you want to deal with the missing data
}
}
Hope it helps :)
This is something that worked up to now and now it just, stopped working (I know, weird, there's probably some silly mistake..)
I have a TripsVM, which contains a list of trips. I load these in my service, returning a List<>.
The problem occurs when I iterate over the trips collection and try to get trip.TripCategory.Name, as the TripCategory is empty, even though TripCategoryID has a value.
This all happens at the backend, I load the trips and then try to iterate over them, they are not being send from the page.
I could probably just load the trip by trip itself, but it used to work and this bug just came up after months of usage.
Any suggestions of where to look for bugs would be really appreciated.
Thanks
Error:
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Where error occurs:
foreach (Trip trip in tripsVM.TripsList) {
var a = trip.TripCategory.Name;
TripsVM:
private List<Trip> _TripsList;
public List<Trip> TripsList
{
get
{
if (_TripsList == null)
{
_TripsList = TripsService.GetTrips();
if (_TripsList == null)
_TripsList = new List<Trip>();
}
return _TripsList;
}
set { _TripsList = value; }
}
Service:
public static List<Trip> GetTrips()
{
return DB.Trips.Where(...).OrderBy(...).ToList();
}
Trip class:
public partial class Trip
{
public int TripID { get; set; }
public int TripCategoryID { get; set; }
....
public virtual TripCategory TripCategory { get; set; }
}
Its looks like your DB context disposed before foreach code or LazyLoadingEnabled set to false in context.
In Service add using
using System.Data.Entity;
And modify loading method
public static List<Trip> GetTrips()
{ return DB.Trips.Where(...).Include(t=>t.TripCategory).OrderBy(...).ToList(); }
I think your code looks fine but you should add some if statements to avoid null exception, because you are returning something with where clause, so you might end up with empty query result and empty list, and in that list you are trying to reach an element of a list object:
if(tripsVM.TripsList != null){
foreach (Trip trip in tripsVM.TripsList) {
var a = trip.TripCategory.Name;
}
}
else
{
// handle empty list
}
private List<Trip> _TripsList;
public List<Trip> TripsList
{
get
{
_TripsList = new List<Trip>();
if(TripsService.GetTrips() != null)
{
_TripsList.add(TripsService.GetTrips());
}
return _TripsList;
}
set { _TripsList = value; }
}
I have the following:
using CommonSettings = MyProject.Commons.Settings;
public class Foo
{
public static void DoSomething(string str)
{
//How do I make sure that the setting exists first?
object setting = CommonSettings.Default[str];
DoSomethingElse(setting);
}
}
If you are using a SettingsPropertyCollection you have to loop and check which settings exists yourself it seems, since it doesn't have any Contains-method.
private bool DoesSettingExist(string settingName)
{
return Properties.Settings.Default.Properties.Cast<SettingsProperty>().Any(prop => prop.Name == settingName);
}
Depending on what type CommomSettings.Default is, a simple null check should be fine:
if(setting != null)
DoSomethingElse(setting);
If you want to check BEFORE trying to retrieve the setting, you need to post the Type of CommonSettings.Default. It looks like a Dictionary so you might be able to get away with:
if(CommonSettings.Default.ContainsKey(str))
{
DoSomethingElse(CommonSettings.Default[str]);
}
try
{
var x = Settings.Default[bonusMalusTypeKey]);
}
catch (SettingsPropertyNotFoundException ex)
{
// Ignore this exception (return default value that was set)
}
This is how you deal with it:
if(CommonSettings.Default.Properties[str] != null)
{
//Hooray, we found it!
}
else
{
//This is a 'no go'
}
You could do the following:
public static void DoSomething(string str)
{
object setting = null;
Try
{
setting = CommonSettings.Default[str];
}
catch(Exception ex)
{
Console.out.write(ex.Message);
}
if(setting != null)
{
DoSomethingElse(setting);
}
}
This would ensure the setting exists - you could go a bit further and try and catch the exact excetion - e.g catch(IndexOutOfBoundsException ex)
I would like to get property name when I'm in it via reflection. Is it possible?
I have code like this:
public CarType Car
{
get { return (Wheel) this["Wheel"];}
set { this["Wheel"] = value; }
}
And because I need more properties like this I would like to do something like this:
public CarType Car
{
get { return (Wheel) this[GetThisPropertyName()];}
set { this[GetThisPropertyName()] = value; }
}
Since properties are really just methods you can do this and clean up the get_ returned:
class Program
{
static void Main(string[] args)
{
Program p = new Program();
var x = p.Something;
Console.ReadLine();
}
public string Something
{
get
{
return MethodBase.GetCurrentMethod().Name;
}
}
}
If you profile the performance you should find MethodBase.GetCurrentMethod() is miles faster than StackFrame. In .NET 1.1 you will also have issues with StackFrame in release mode (from memory I think I found it was 3x faster).
That said I'm sure the performance issue won't cause too much of a problem- though an interesting discussion on StackFrame slowness can be found here.
I guess another option if you were concerned about performance would be to create a Visual Studio Intellisense Code Snippet that creates the property for you and also creates a string that corresponds to the property name.
Slightly confusing example you presented, unless I just don't get it.
From C# 6.0 you can use the nameof operator.
public CarType MyProperty
{
get { return (CarType)this[nameof(MyProperty)]};
set { this[nameof(MyProperty)] = value]};
}
If you have a method that handles your getter/setter anyway, you can use the C# 4.5 CallerMemberName attribute, in this case you don't even need to repeat the name.
public CarType MyProperty
{
get { return Get<CarType>(); }
set { Set(value); }
}
public T Get<T>([CallerMemberName]string name = null)
{
return (T)this[name];
}
public void Set<T>(T value, [CallerMemberName]string name = null)
{
this[name] = value;
}
I'd like to know more about the context in which you need it since it seems to me that you should already know what property you are working with in the property accessor. If you must, though, you could probably use MethodBase.GetCurrentMethod().Name and remove anything after get_/set_.
Update:
Based on your changes, I would say that you should use inheritance rather than reflection. I don't know what data is in your dictionary, but it seems to me that you really want to have different Car classes, say Sedan, Roadster, Buggy, StationWagon, not keep the type in a local variable. Then you would have implementations of methods that do the proper thing for that type of Car. Instead of finding out what kind of car you have, then doing something, you then simply call the appropriate method and the Car object does the right thing based on what type it is.
public interface ICar
{
void Drive( decimal velocity, Orientation orientation );
void Shift( int gear );
...
}
public abstract class Car : ICar
{
public virtual void Drive( decimal velocity, Orientation orientation )
{
...some default implementation...
}
public abstract void Shift( int gear );
...
}
public class AutomaticTransmission : Car
{
public override void Shift( int gear )
{
...some specific implementation...
}
}
public class ManualTransmission : Car
{
public override void Shift( int gear )
{
...some specific implementation...
}
}
Use MethodBase.GetCurrentMethod() instead!
Reflection is used to do work with types that can't be done at compile time. Getting the name of the property accessor you're in can be decided at compile time so you probably shouldn't use reflection for it.
You get use the accessor method's name from the call stack using System.Diagnostics.StackTrace though.
string GetPropertyName()
{
StackTrace callStackTrace = new StackTrace();
StackFrame propertyFrame = callStackTrace.GetFrame(1); // 1: below GetPropertyName frame
string properyAccessorName = propertyFrame.GetMethod().Name;
return properyAccessorName.Replace("get_","").Replace("set_","");
}
FWIW I implemented a system like this:
[CrmAttribute("firstname")]
public string FirstName
{
get { return GetPropValue<string>(MethodBase.GetCurrentMethod().Name); }
set { SetPropValue(MethodBase.GetCurrentMethod().Name, value); }
}
// this is in a base class, skipped that bit for clairty
public T GetPropValue<T>(string propName)
{
propName = propName.Replace("get_", "").Replace("set_", "");
string attributeName = GetCrmAttributeName(propName);
return GetAttributeValue<T>(attributeName);
}
public void SetPropValue(string propName, object value)
{
propName = propName.Replace("get_", "").Replace("set_", "");
string attributeName = GetCrmAttributeName(propName);
SetAttributeValue(attributeName, value);
}
private static Dictionary<string, string> PropToAttributeMap = new Dictionary<string, string>();
private string GetCrmAttributeName(string propertyName)
{
// keyName for our propertyName to (static) CrmAttributeName cache
string keyName = this.GetType().Name + propertyName;
// have we already done this mapping?
if (!PropToAttributeMap.ContainsKey(keyName))
{
Type t = this.GetType();
PropertyInfo info = t.GetProperty(propertyName);
if (info == null)
{
throw new Exception("Cannot find a propety called " + propertyName);
}
object[] attrs = info.GetCustomAttributes(false);
foreach (object o in attrs)
{
CrmAttributeAttribute attr = o as CrmAttributeAttribute ;
if (attr != null)
{
// found it. Save the mapping for next time.
PropToAttributeMap[keyName] = attr.AttributeName;
return attr.AttributeName;
}
}
throw new Exception("Missing MemberOf attribute for " + info.Name + "." + propertyName + ". Could not auto-access value");
}
// return the existing mapping
string result = PropToAttributeMap[keyName];
return result;
}
There's also a custom attribute class called CrmAttributeAttribute.
I'd strongly recommend against using GetStackFrame() as part of your solution, my original version of the solution was originally the much neater:
return GetPropValue<string>();
But it was 600x slower than the version above.
Solution # 1
var a = nameof(SampleMethod); //a == SampleMethod
var b = nameof(SampleVariable); //b == SampleVariable
var c = nameof(SampleProperty); //c == SampleProperty
Solution # 2
MethodBase.GetCurrentMethod().Name; // Name of method in which you call the code
MethodBase.GetCurrentMethod().Name.Replace("set_", "").Replace("get_", ""); // current Property
Solution # 3
from StackTrace:
public static class Props
{
public static string CurrPropName =>
(new StackTrace()).GetFrame(1).GetMethod().Name.Replace("set_", "").Replace("get_", "");
public static string CurrMethodName =>
(new StackTrace()).GetFrame(1).GetMethod().Name;
}
you just need to call Props.CurrPropName or Props.CurrMethodName
Solution # 4
Solution for .NET 4.5+:
public static class Props
{
public static string GetCallerName([System.Runtime.CompilerServices.CallerMemberName] String propertyName = "")
{
return propertyName;
}
}
usage: Props.GetCallerName();
Yes, it is!
string test = "test string";
Type type = test.GetType();
PropertyInfo[] propInfos = type.GetProperties();
for (int i = 0; i < propInfos.Length; i++)
{
PropertyInfo pi = (PropertyInfo)propInfos.GetValue(i);
string propName = pi.Name;
}
Try using System.Diagnostics.StackTrace to reflect on the call stack. The property should be somewhere in the call stack (probably at the top if you're calling it directly from the property's code).