简体   繁体   中英

Storing objects as references?

I'm not entirely sure if what I want is possible or not, be here's what I want:

I have a couple collection of different objects that I am storing. Let's say a collection of Users and a collection of Projects .

Here are some examples of what they might look like:

public class User
{
    public int UserId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string EmailAddress { get; set; }

    public List<Project> Projects { get; set;} 
}

public class Project
{
    public int ProjectId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public User Manager { get; set; }
}

As you can see, a User can have multiple projects, while a Project has a User.

Basically when I have these stored, I want to be able to edit a User in the collection of Users and automatically have any Projects with that User be updated to contain the updated information about that User. Subsequently, if I update a Project any Users with that Project will automatically have their Project updated. Like some way of storing references to the objects rather than values?

Is there any way of doing this?

What you have here are object references . That means, as long as you are referring to the same object ( instance ), by default everything works as you'd expect.

Example (using your classes):

User u = new User();
Project p = new Project();
p.Manager = u;
u.Projects.Add(p);

This creates an empty user and an empty project. The project references the user, the user's project list references the project.

Now you change the name of the user and the project:

u.FirstName = "Test";
u.LastName = "User";

This will allow you to get the following result:

Console.WriteLine("{0} {1}", p.Manager.FirstName, p.Manager.LastName);
=> Test User

Another thing you can do now is this:

User userInfo = p.Manager;
userInfo.EMailAddress = "test@company.org";

This will reflect whatever way you access the user object you've assigned, as all these "variables" are "pointing" to the same object instance (they reference the same object in memory).

You can even pass your object reference to another method:

public void ChangeProjectManagerEmail(Project theProject, string newEMail)
{
    theProject.Manager.EMailAddress = newEMail;
}

Calling the above method like this:

ChangeProjectManagerEmail(p, "hello@world.com");

Will result in this:

Console.WriteLine(u.EMailAddress);
=> hello@world.com

What does not work is this :

User anotherUser = new User();
anotherUser.UserId = 5;

Console.WriteLine(p.Manager.UserId);

This will output 0 , as the new user anotherUser is not referenced by any other object.

You do need to be careful when it comes to persisting such a structure. While storing it (in a file, a database, etc.) is pretty easy, you need to make sure that you re-create the exact same object structure when reading the data. Imagine this:

  • Project 1 references User u1
  • Project 2 references User u1
  • u1 references Project 1 and 2

Now first of all you need to decide whether you want to persist per user or per project, otherwise you might do duplicate work. When restoring the persisted information you need to make sure that you create only one user ! (it's best to use the unique ID to check whether the user has already been restored). Otherwise you'll end up with two distinct User objects with the same information and you will wonder why changing the user only reflects for one project. The worst case would be that after changing the user information you'll end up with two users with the same ID but different information in your storage.


All that said: WATCH OUT ! Your object structure is somewhat dangerous in terms of cross-references. As it is now, it is very well possible to add a project to a user which references a totally different user as its manager. Example:

User user1 = new User();
// Initialize ID, name, etc.

User user2 = new User();
// Initialize ID, name, etc.

Project p = new Project();
// Initialize stuff
p.Manager = user2;

user1.Projects.Add(p);

See the problem here?

You can implement the Observer Design Pattern to notify the 'observers' when a particular object changes.

"The observer design pattern requires a division between an observer, Which registers for notifications, and the provider, Which monitors data and sends notifications to one or more observers."

See the implementation of this Pattern in Dot Net:

https://msdn.microsoft.com/en-us/library/ff506346(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/ee817669.aspx

If you want that only the database level, you can create a trigger "ON UPDATE" to make the desired changes.

你为什么不只是保持用户ID的项目,当你需要知道这个项目是属于只运行一个谁selectusers.select(x => x.userid == project.userid)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM