将对象存储为引用?

时间:2016-08-17 13:18:01

标签: c# .net

我不完全确定我想要的是否可能,这就是我想要的:

我正在存储一些不同的对象。我们假设Users的集合和Projects的集合。

以下是一些可能的示例:

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; }
}

如您所见,用户可以有多个项目,而项目有用户。

基本上,当我存储这些内容时,我希望能够在用户集合中编辑用户,并自动更新任何包含该用户的项目以包含有关该用户的更新信息。随后,如果我更新项目,那么具有该项目的任何用户将自动更新其项目。就像某种存储对象的引用而不是值的方式一样?

有没有办法做到这一点?

3 个答案:

答案 0 :(得分:3)

这里有你的对象引用。这意味着,只要您指的是相同的对象实例),默认情况下一切都会按照您的预期运行。

示例(使用您的课程):

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

这会创建一个空用户和一个空项目。项目引用用户,用户的项目列表引用项目。

现在您更改用户和项目的名称:

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

这将使您获得以下结果:

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

你现在可以做的另一件事是:

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

这将反映您访问所分配的用户对象的任何方式,因为所有这些“变量”都“指向”同一对象实例(它们引用内存中的同一对象)。

您甚至可以将对象引用传递给另一种方法:

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

调用上面的方法:

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

会导致这个:

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

不起作用

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

Console.WriteLine(p.Manager.UserId);

这将输出0,因为新用户anotherUser未被任何其他对象引用。

在坚持这样的结构时,你需要小心。存储它(在文件,数据库等中)非常简单,您需要确保在读取数据时重新创建完全相同的对象结构。想象一下:

  • 项目1引用用户u1
  • 项目2引用用户u1
  • u1引用项目1和2

首先,您需要决定是要保留每个用户还是每个项目,否则您可能会重复工作。当恢复持久性信息时,您需要确保只创建一个用户! (最好使用唯一ID来检查用户是否已经恢复)。否则,您最终会得到两个具有相同信息的不同User个对象,您会想知道为什么更改用户仅反映一个项目。最糟糕的情况是,在更改用户信息后,您最终会得到两个具有相同ID但存储中信息不同的用户。

所有这一切:观看!在交叉引用方面,您的对象结构有些危险。就像现在一样,很有可能将一个项目添加到一个用户,该用户将一个完全不同的用户作为其管理者。例如:

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);

在这里查看问题?

答案 1 :(得分:0)

您可以实施观察者设计模式,以便在特定对象发生变化时通知“观察者”。

“观察者设计模式需要在注册通知的观察者与提供者之间进行划分,提供者监视数据并向一个或多个观察者发送通知。”

请参阅Dot Net中此模式的实现:

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

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

如果只想要数据库级别,可以创建一个“ON UPDATE”触发器来进行所需的更改。

答案 2 :(得分:0)

为什么不在项目中保留用户ID,当您需要知道项目所属的人时,只需运行select users.select(x => x.userid == project.userid)