Reputation: 767
I have a list of clients and a list of rooms. A Room
can have many clients, a Client
can only be in one Room
.
I created a list in my Room
class to contain references to its clients and also a reference in my Client
class to keep a reference to the Room
it's currently in.
The problem is that someone could add a Client
to a Room
without setting the Room
reference in the Client
to the same Room
(or to any room at all for that matter).
The best I have come up with is to wrap the client list in a custom class with a custom Add method that sets the clients room reference to the room it's being added to. That way someone could still set the clients room reference without adding it to that room so then I would have to customize the clients room reference setter so that it Adds itself to the referenced Rooms list of clients whenever it is set. I would have to add some checks to avoid infinite recursion. Feels a little clunky.
Thanks
Upvotes: 1
Views: 138
Reputation: 509
If you do not want to solve the problem through databases, then one solution might be that you make your list of clients private and make a public method for adding a new Client in your Room class and control references integrity in your Client class.
Room.cs
class Room
{
public int RoomId { get; set; }
public decimal Price { get; set; }
public string RoomNumber { get; set; }
private List<Client> Clients { get; set; }
public void AddClient(Client client)
{
if (client != null && !Clients.Contains(client))
{
Clients.Add(client);
// after adding client to the current room
// (re)assign his room to the current room
client.Room = this;
}
}
public void RemoveClient(Client client)
{
if (client != null && Clients.Contains(client))
Clients.Remove(client);
/*else
throw new System.Exception($"There is no clien assigned to the room: {this.RoomNumber}");*/
}
public Room(int id, decimal price, string roomNumber)
{
RoomId = id;
Price = price;
RoomNumber = roomNumber;
Clients = new List<Client>();
}
}
Client.cs
class Client
{
public int ClientId { get; set; }
public string FullName { get; set; }
private Room _room;
public Room Room
{
get => _room;
set
{
// Check if the Client is assigned to any room
if (value != null && _room == null)
{
_room = value;
// add client to the new room
value.AddClient(this);
}
// If the Client is currently assigned to any room
// and we want to just reassign it from it
else if(value == null && _room != value)
{
_room.RemoveClient(this);
_room = null;
}
// If the Client is currently assigned to any room
// and we want to assign him to another room
else if(value != null && _room != value && _room != null)
{
_room.RemoveClient(this);
value.AddClient(this);
_room = value;
}
}
}
public Client(int id, string fullName, Room room = null)
{
ClientId = id;
FullName = fullName;
Room = room;
}
}
Some usage:
Program.cs
class Program
{
static void Main(string[] args)
{
Room room = new Room(1, 250, "Room 1");
Room room1 = new Room(2, 200, "Room 2");
Client client = new Client(1, "Client1");
Client client2 = new Client(2, "Client2");
Client client3 = new Client(3, "Client3");
// Add clients to room through Room's object method
room.AddClient(client);
room.AddClient(client2);
room.Clients.ForEach(c => WriteLine(c.FullName));
WriteLine();
/* Output:
* Client1
* Client2
*/
// Assign client3 to room1 through Client's 'room object'
client3.Room = room1;
room1.Clients.ForEach(c => WriteLine(c.FullName));
WriteLine();
/* Output:
* Client3
*/
// Reassign client to another room
client.Room = room1;
room1.Clients.ForEach(c => WriteLine(c.FullName));
WriteLine();
/* Output:
* Client3
* Client1
*/
room.Clients.ForEach(c => WriteLine(c.FullName));
WriteLine();
/* Output:
* Client2
*/
// Try to assign client to his current Room --> it will not add
client.Room = room1;
room1.Clients.ForEach(c => WriteLine(c.FullName));
WriteLine();
/* Output:
* Client3
* Client1
*/
// Remove client through Room's object method
room1.RemoveClient(client);
room1.Clients.ForEach(c => WriteLine(c.FullName));
WriteLine();
/* Output:
* Client3
*/
// Try to remove not existing client from Room --> it will not remove any
room1.RemoveClient(client);
// Reassign client from room --> client3's reference from room1.Clients will be removed
client3.Room = null;
room1.Clients.ForEach(c => WriteLine(c.FullName));
/* Output:
*
*/
}
}
Basically, we need to control the references through objects all the time. And be careful during the implementation, because sometimes it might confuse you, and incorrect implementation might lead to StackOverflow (continuously adding, removing references continuously), not adding or removing references in different situations, so you might want to test for different cases before using.
Upvotes: 2