Generate a unique ID to a body property of an object that's CONSISTENT through runtime and presents no overhead to the developer on implementation

This problem is a bit hard to expose via the title so I hope the following clarifies my intentions a bit.

Suppose you have the following data classes:

class abstract Employee {       string ID;   }  class FullTimeEmployee : Employee {       string schedule;  }  class PartTimeEmployee : Employee{       string schedulePartTime;  }  class WheelsSpecialist : Employee{ }  class InteriorsSpecialist : Employee{ }  class Workshop {      WheelsSpecialist wheely_guy;      InteriorsSpecialist interiors_guy;  } 

Now, suppose that I instantiate my workshop as follows:

var Workshop = new Workshop{        wheely_guy = new PartTimeEmployee(),        interiors_guy = new FullTimeEmployee(); } 

Please assume that the structure / inheritance and instantiations here provided are immutable.

What I’d like is to generate an ID set on Employee.ID that survives the runtime and is consist and independent from class properties / developer implementation.

Understand also that: The path of each object property in the workshop instantiation is guaranteed to be UNIQUE.

As so, a good ID for the WheelsSpecialist in Workshop.wheely_guy would be "Workshop.wheely_guy". (for example) because no path will ever be the same when I’m instantiating the workshop.

When I access the object "Workshop.wheely_guy.ID" I’d like to have "Workshop.wheely_guy" there or something analogous.

I imagine something like this would work (non valid C#, logic intact):

class PartTimeEmployee {      //instantiationPath is for example, "Workshop.wheely_guy"     onCreate(string instantiationPath){          this.ID = instantionPath;      }      } 

I’ve tried this with StackTrace and whatnot, but couldn’t find a way of doing it right.

Whether this instantiationPath method is used or not, the solution requires that:

  • I get to keep my structure as is in the example EXCEPT for properties. Those can change.
  • When I want to add a new dimension to my workshop variable I CAN’T, as a developer, be responsible for awarding a class it’s own unique property.

As so, doing something like "this.ID = wheels" manually is not an option (also, depending this ID on properties that the developer must implement is also not viable).

Can this be done some way that meets my demands?

Thank you!

Add Comment
1 Answer(s)

The provided code does not compile, and the object design/inheritance used seems a bit off. You probably want to work on the abstractions themselves. But that is not what you asked (mainly). It’s kind of hard to figure out what exactly you asked, but I will do my best to answer what I think you asked (mostly):

"I want a field of an object instance to contain an automatically calculated navigation path by which it is accessible in some collection or composite object unrelated to the object itself" -> while close to impossible in C#, this might be entirely/easily possible in other languages. Still, the concept itself seems a little off.

The premise here is that the Employee object does not and should not know about the Workshop object Think about part-time employees trying to work separate shifts in separate workshops at the same time, and other possible changes in the business logic regarding Employees and Workshops.

Let’s walk through some of the possibilities, ordered by viability:

  1. Doing some magic at constructor/instantiation time in the abstract constructor code (Stack Frame walking, callerMember tricks, Reflection?, AST parsing?) At instantiation, in a constructor, the stack trace does not contain information about which property/field it is about to be assigned to (if at all for that matter, it might just need to be instantiated, not assigned to anything). So there is no way to set such an id at constructor time.

  2. Doing some magic in the Id property getter There is no way to pass in parameters to a property getter, so we run into the same type of problem as with option 1: the stack trace contains no useful information by the time the getter is accessed.

  3. Make the Employee object know about Workshop No, just no.

  4. Some weird runtime/weaving magic to "calculate" these paths when they are accessed? Maybe, but how much effort to put in and to what purpose?

  5. Expression parsing in a separate method:

//Left out the non-compiling code. public static void Main(string[] args) {     var Workshop = new Workshop     {         WheelsGuy = new PartTimeEmployee(),         InteriorsGuy = new FullTimeEmployee()     };     Console.WriteLine(GetObjectAccessPath((_) => Workshop.WheelsGuy)); }  public static string GetObjectAccessPath(Expression<Func<Workshop, Employee>> member) {     string body = member.Body.Reduce().ToString();     // the line below might take some tweaking depending on your needs     return body.Substring(body.IndexOf($"{nameof(Workshop)}")); } // Output: Workshop.WheelsGuy 
  1. Use Reflection in a separate method to "get" a list of properties that are of any type derived from Employee and based on that Generate a list of ids with something like properties.Select(p => $"Workshop_{p.Name}");

Most viable: Re-design the object model: (This is my opinion, and the requirements of your project might be different. Even if I am speculating here, the same principles presented here would apply in many other ways).

Extract more abstractions, like Position, Role, and Schedule. Part-time would be a schedule. Wheels guy would be a role. Position would be "an employee that fulfills the role of wheels guy at a workshop." There might be more examples (pay by hour/week/month, tax exemption, etc.).

As a rule, holding too many concerns in one class is a code smell and will get you in trouble quick. You can choose to carve up the classes however you want, but for what you "seem" to want, this part is important: have a class that represents the relationship between employee and workshop.

For example, instead of the Workshop holding instances of Employees: the Position class would hold/know about an Employee, his Role, his Schedule, and the Workshop he works at. The Position’s Id could then easily be Id => $"Workshop_{Role}"; or Id => $"{WorkShop}_{Role}", etc. As a bonus, you get the design bonus of the Workshop being free from knowing which types of employees it might hold.

In general, I’d suggest you look into SOLID principles, it’s an eye opener.

Add Comment

Your Answer

By posting your answer, you agree to the privacy policy and terms of service.