I have next 3 classes
class Review
{
public int Id{get; set;}
public string Text{get; set;}
public ICollection<Comment> Comments{get; set;}
//some additional properties
}
class User
{
public int Id{get; set;}
public string Name{get; set;}
public string Login{get; set;}
public ICollection<Comment> Comments{get; set;}
//some additional properties
}
class Comment
{
public int Id{get; set}
public string Comment{get; set;}
public ??? Target{get; set;}
}
In this context, a Target is what the comment was attached to. And for some things, I need to know exactly who the target is - a specific user or a specific review. And inheriting from the interface is not suitable due to the strong distinction in the parameters. And i need to use database so object type not for that kind of situation(as i know).
From the code provided you can use object
or dynamic
for Target
.
But you may prefer using a base class for Review
and User
like BaseObjectWithComments
to be able to write BaseObjectWithComments Target
, which is a little better.
So we can move some members to this root class.
Also we can add a constructor for Comment
to pass the owner.
public abstract class BaseObjectWithIdAndComments
{
public int ID { get; set; }
public ICollection<Comment> Comments { get; set; }
}
public class Review : BaseObjectWithIdAndComments
{
public string Text { get; set; }
}
public class User : BaseObjectWithIdAndComments
{
public string Name { get; set; }
public string Login { get; set; }
}
public class Comment
{
public int ID { get; set; }
public string Text { get; set; }
public BaseObjectWithIdAndComments Target { get; set; }
public Comment(BaseObjectWithIdAndComments owner, int id, string comment)
{
Target = owner;
ID = id;
Text = comment;
}
}
Test
var review = new Review();
var user = new User();
review.Comments = new List<Comment>();
user.Comments = new List<Comment>();
review.Comments.Add(new Comment(review, 1, "review comment 1"));
review.Comments.Add(new Comment(review, 2, "review comment 2"));
user.Comments.Add(new Comment(user, 1, "user comment 1"));
user.Comments.Add(new Comment(user, 2, "user comment 2"));
Console.WriteLine("Owner of review comment #1: " + review.Comments.ElementAt(0).Target.GetType().Name);
Console.WriteLine("Owner of user comment #2: " + user.Comments.ElementAt(1).Target.GetType().Name);
Output
Owner of review comment #1: Review
Owner of user comment #2: User
About using a database, you need to change the design.
For example the fields of the table may be like:
CommentID
ReviewID
UserID
Text
But this is not clean, so you may prefer to have 2 tables to be more conventionnal: UserComments
and ReviewComments
, thus each of these tables will have a OwnerID
pointing to Users
or Reviews
.
Thus you can load data in the instances of the previous classes while setting the owner reference as indicated.
Maybe you can consider using an ADO.NET typed DataSet that does all the work for you while being able to use Visual Studio RAD Designers:
How to: Create and configure datasets in Visual Studio (MS Docs)