Using an object property for a key in a dictionary

I would like to use the property of objects as a key for a dictionary. It can be done?

The ultimate goal for this is to use this so that you can see whether the property is locked or not, in different states in which the object may be. These locked values ​​are not saved, they simply exist in the business rules for the model.

The ideal code to see if a field is locked would look like this:

bool ageLocked = myObject.IsFieldLocked( x => x.Age); bool nameLocked = myObject.IsFieldLocked(x => x.Name); 

IsFieldLocked is an extension method for type myObject.

I would like the dictionary to work in myObject and be replaced by various variations of the dictionary based on the state of the object, for example, place an order or expect an order, have different dictionary definitions.

Hope I can use factory to create different variations of the dictionary;

 Factory.CreateAwaitingOrderLockedFields() Factory.CreateOrderPlacedLockedFields() 

Defining a dictionary like this

 new Dictionary< ***MissingMagic***, bool>() { { x => x.Age , true}, { x => x.Name, false} } 

The goal is to avoid the key being a string, a strongly typed key is much more desirable.

+4
source share
5 answers

I would define the dictionary simply as Dictionary<string, bool> .

Then the extension method might look something like this:

 public static bool IsFieldLocked<TField>(this MyClass self, Expression<Func<MyClass, TField>> propertyExpression) { // note: null checks etc omitted for brevity var lambda = (LambdaExpression)propertyExpression; MemberExpression memberExpression; if (lambda.Body is UnaryExpression) { var unaryExpression = (UnaryExpression)lambda.Body; memberExpression = (MemberExpression)unaryExpression.Operand; } else { memberExpression = (MemberExpression)lambda.Body; } string propertyName = memberExpression.Member.Name; return self.InternalLockedFieldsDictionary[propertyName]; } 
+4
source

Here is my cutting solution based on herzmeister der welten recommendations

  public class MyDtoOne : BaseFieldLockingDto<MyDtoOne> { public string Name { get; set; } public int Age { get; set; } public MyDtoOne() { LockedFields = new LockedFields<MyDtoOne> { { x => x.Age, false }, { x => x.Name, true } }; } } public class MyDtoTwo : BaseFieldLockingDto<MyDtoTwo> { public DateTime DateOfBirth { get; set; } public MyDtoTwo() { LockedFields = new LockedFields<MyDtoTwo> { {x => x.DateOfBirth, false} }; } } public class BaseFieldLockingDto<TBaseObject> { public LockedFields<TBaseObject> LockedFields { get; set; } public bool IsFieldLocked<TField>(Expression<Func<TBaseObject, TField>> propertyExpression) { return LockedFields.IsFieldLocked(propertyExpression); } } public class LockedFields<TBaseObject> : Dictionary<string, bool> { public void Add<TField>(Expression<Func<TBaseObject, TField>> propertyExpression, bool isLocked) { Add(GenerateKey(propertyExpression), isLocked); } private static string GenerateKey<TField>(Expression<Func<TBaseObject, TField>> propertyExpression) { return GetLambdaPropertyName(propertyExpression); } public bool IsFieldLocked<TField>(Expression<Func<TBaseObject, TField>> propertyExpression) { if (Count == 0) return false; string propertyName = GetLambdaPropertyName(propertyExpression); if (ContainsKey(propertyName) == false) return false; return this[propertyName]; } private static string GetLambdaPropertyName<TField>(Expression<Func<TBaseObject, TField>> propertyExpression) { var lambda = (LambdaExpression) propertyExpression; MemberExpression memberExpression; if (lambda.Body is UnaryExpression) { var unaryExpression = (UnaryExpression) lambda.Body; memberExpression = (MemberExpression) unaryExpression.Operand; } else { memberExpression = lambda.Body as MemberExpression; } if (memberExpression == null) { throw new ArgumentException(string.Format("Expression '{0}' refers to a method, not a property.", propertyExpression)); } return memberExpression.Member.Name; } } 

With this, I can do the following:

  private static void Main(string[] args) { var myDtoOne = new MyDtoOne(); bool ageLocked = myDtoOne.IsFieldLocked(x => x.Age); bool nameLocked = myDtoOne.IsFieldLocked(x => x.Name); Console.WriteLine(string.Format("Age locked is {0}", ageLocked ? "true" : "false")); Console.WriteLine(string.Format("Name locked is {0}", nameLocked ? "true" : "false")); myDtoOne.LockedFields = new LockedFields<MyDtoOne> {{x => x.Age, true}, {x => x.Name, false}}; bool ageLocked1 = myDtoOne.IsFieldLocked(x => x.Age); bool nameLocked1 = myDtoOne.IsFieldLocked(x => x.Name); Console.WriteLine(string.Format("Age locked is {0}", ageLocked1 ? "true" : "false")); Console.WriteLine(string.Format("Name locked is {0}", nameLocked1 ? "true" : "false")); var myDtoTwo = new MyDtoTwo(); bool dateOfBirth = myDtoTwo.IsFieldLocked(x => x.DateOfBirth); Console.WriteLine(string.Format("Date of birth locked is {0}", dateOfBirth ? "true" : "false")); myDtoTwo.LockedFields = new LockedFields<MyDtoTwo>() {{x => x.DateOfBirth, true}}; bool dateOfBirth1 = myDtoTwo.IsFieldLocked(x => x.DateOfBirth); Console.WriteLine(string.Format("Date of birth locked is {0}", dateOfBirth1 ? "true" : "false")); Console.ReadLine(); } } 
+1
source

I think you just need to use inheritance. Create the base class LockedField, then create the AwaitingOrderLockedField and OrderPlacedLockedField that inherit this class.

 class LockedField { } class AwaitingOrderLockedField : LockedField { } class OrderPlacedLockedField : LockedField { } 

The dictionary will be IDictionary<LockedField, bool>

0
source

You can declare a dictionary of any type as a key;

 Dictionary<Form,bool> 

will create a dictionary in which form elements will be used as a key.

Is that what you ask?

If you must use several different objects as a key, you can use Dictionary<object,bool> or let all objects inherit from another object Dictionary<masterobject,bool> .

0
source

You will need to implement the IComparable interface in the class that you want to use as a key in the dictionary:

 public class MyObject : IComparable { public int CompareTo(MyObject obj) { // Comparison Logic } } 

Since this is not really an option for a member of an object, you can use Dictionary<string, bool> with the field name as the key and a little reflection in your IsFieldLocked() method to cut the string out of a heavily printed field.

0
source

All Articles