[CSHARP-3868] Using internal constructor of any ValueObject par of an aggregate is not possible ? Created: 20/Sep/21  Updated: 27/Oct/23  Resolved: 12/Oct/21

Status: Closed
Project: C# Driver
Component/s: BSON
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Minor - P4
Reporter: Nicolas REY Assignee: Dmitry Lukyanov (Inactive)
Resolution: Gone away Votes: 0
Labels: DDD, constructor, serialization
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: PNG File image-2021-09-20-11-29-58-718.png    

 Description   

Hi,

I would like to work with Domain Driven Design Tactical patterns, using MongoDb as the storage engine of my aggregates.

To ensure object encapsulation I need to provide internal scoped constructor (for internal object creation in my Domain layer), and public factories for extra domain layer object creation.

 

Example :

Aggregate 

    public class FlashInfo : AggregateRoot<FlashInfoId>
    {
        public Information Text { get; private set; }
        public DateTime ActivationDate { get; private set; }
        public DateTime? LastModified { get; private set; }
        public User CreatedBy { get; private set; }
        public User ModifiedBy { get; private set; }
    
     // ...
 
    }

Value Object 

    public class Information : Value<Information>
    {
       public string Text { get; } // Satisfy the serialization requirements 
       internal Information(string text)
        {
            Text = text;
        }        
 
        public static implicit operator string(Information info) => info.Text;
            
        public static Information CreateInformation(string text)
        {
            CheckValidity(text);
            return new Information(text);
        }
 
        private static void CheckValidity(string text)
        {
            if (string.IsNullOrEmpty(text))
                throw new InformationTextIsEmptyException("The information text must not be null or empty");            
 
if (text.Length > 100)
                throw new ArgumentOutOfRangeException(nameof(text), "The information text cannot be longer that 100 characters");
        }
    }



 Comments   
Comment by PM Bot [ 12/Oct/21 ]

There hasn't been any recent activity on this ticket, so we're resolving it. Thanks for reaching out! Please feel free to comment on this if you're able to provide more information.

Comment by Nicolas REY [ 22/Sep/21 ]

Hi ! 

Thank you for your feedback, I'll give it a try

Comment by Dmitry Lukyanov (Inactive) [ 20/Sep/21 ]

Hey nicolasrey@laposte.net,

We don't support internal ctor since from mongo driver point of view, it's the same as private one. And we still need to instantiate it.
If you can use mongo configuration in an assembly where your class with internal ctor is defined, you can try this workaround:

 BsonClassMap.RegisterClassMap<TestWithInternalCtor>(e =>
{
         e.AutoMap();
         e.MapCreator(c => new TestWithInternalCtor(c.A, c.B));
         e.MapMember(c => c.A);
         e.MapMember(c => c.B);
});
 
 public class TestWithInternalCtor
 {
       internal TestWithInternalCtor(int a, int b)
       {
            A = a;
            B = b;
       }
 
       public int A { get; }
       public int B { get; }
 }

Comment by Nicolas REY [ 20/Sep/21 ]

Well I missed the end of the message, can't find how to edit it ... :

 

Then on persisting my object, the Information VO is set to an empty object in MongoDb.

When I use a public constructor for my nformation VO instead of the object persisted is correct (with it's value)

Any possibility to use an internal constructor their ?

Thank you

Generated at Wed Feb 07 21:46:32 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.