How to create an instance of a derived class from an instance of the base class and enable private fields?

My question relates to this question , but a little more specifically.

I have a Customer domain object that looks like this:

 public class Customer : Party { public Identity Identity {get; protected set;} public bool IsOrganization {get; set;} } 

and Identity is as follows:

 public class Identity : PersistableModel { public string FirstName { get; set; } public string LastName { get; set; } public string MiddleInitial { get; set; } public string Title { get; set; } public string BusinessName { get; set; } public string LegalName { get; set; } public bool IsSynchronized { get; private set; } } public abstract class PersistableModel : IPersistableModel { public const long UnassignedId = 0; public static readonly DateTime MinimumDateTime = new DateTime(1900, 1, 1); private readonly List<string> modifiedProperties = new List<string>(); public virtual ModelState State { get; set; } public IEnumerable<string> ModifiedProperties { get { return modifiedProperties; } } protected bool HasModifiedProperties { get { return 0 < modifiedProperties.Count; } } public bool WasModified(string propertyName) { return modifiedProperties.Contains(propertyName); } public void WasModified(string propertyName, bool modified) { if (modified) { if (!WasModified(propertyName)) modifiedProperties.Add(propertyName); } else { modifiedProperties.Remove(propertyName); } } public virtual void OnPersisting() { } public abstract void Accept(Breadcrumb breadcrumb, IModelVisitor visitor); } 

Now, based on the value of IsOrganization, you need to change some logic in Identity, especially if IsOrganization is true. Separate related fields (first name, last name, etc.) must return null when it is false. Organization fields must return null.

Previously, this was done using various client implementations that would initialize the identification for another base class in their constructors, however, the change I'm working on requires removing the separation of the classes of the two client types.

I thought the Identity property looked something like this:

 public override Identity Identity { get { if (IsOrganization) { return OrgnaizationIdentity.FromIdentity(base.Identity); } else { return IndividualIdentity.FromIdentity(base.Identity); } } } 

and the From Identity method looks like this:

 public static OrgnaizationIdentity FromIdentity(Identity identity) { return new OrgnaizationIdentity { FirstName = identity.FirstName, LastName = identity.LastName, MiddleNameInitial = identity.MiddleNameInitial, Title = identity.Title }; } 

The problem is that the original identification object has some private fields that must also be returned.

So my question is: is there an accepted way to do something like this?

+6
source share
2 answers

The copy constructor can do this if you can add and use it:

 class Identity { private int x; public Identity(Identity that) { this.x = that.x; } } class OrgnaizationIdentity : Identity { public OrgnaizationIdentity(Identity that) : base(that) { ... } } 
+4
source

I’m not sure why you didn’t just mark the attributes as public or even protected if they are really subclassed (I assume they are), but this is a hack.

Why not create static factory methods in the Identity class? So you have access to private Identity members? It seems to me that you are implementing an anti-pattern known as the Anemic Data Model, having other classes responsible for creating another business object.

Why couldn't you add something like this to your Identity class:

 public static Identity CreateIdentity(Customer from) { Identity newId = null; //call other factory.... if (from.IsOrganization) { newId = OrgnaizationIdentity.FromIdentity(from); } else { newId = IndividualIdentity.FromIdentity(from); } //populate Identity private attribs here... } 

This allows other factory methods to subclass ... but allows Identity factory to see private vars ...

+1
source

Source: https://habr.com/ru/post/973716/


All Articles