Search code examples
c#classnestedreset

How to Reset members of an instance Class without recreate a new instance?


I'd like to Reset to there default values all of the members of my class instance CommunicationErrorsDetails. This class is part of a nested class MyNestedClassInstance.

This is what I'd like to do :

MyNestedClassInstance.CommunicationErrorsDetails.Reset()

This a sample of my nested class MyNestedClass which instance is MyNestedClassInstance :

public class MyNestedClass : ICloneable
{
    ...

    /// <summary>
    /// Communication errors count
    /// </summary>
    public class CommunicationErrorsDetailsType : ICloneable
    {
        public int RetryCount;
        public int CRCErrorCount;
        public int DataBytesNotExpectedCount;
        public int TooMuchDataReceivedCount;
        public int ResponseDataAddressNotEqualCount;
        public int BytesReceivedInCommunicationStateStartCount;
        public int BytesReceivedInCommunicationStateSendFrameCount;
        public int BytesReceivedInCommunicationStateDataResponseReceivedCount;
        public int ExceptionCount;
        public int NakcReceivedCount;
        public int AckTimeoutCount;
        public int DataTimeoutCount;
        public double DataTimeoutRate;

        public bool HasCommunicationErrors
        {
            get => RetryCount > 0
                || CRCErrorCount > 0
                || DataBytesNotExpectedCount > 0
                || TooMuchDataReceivedCount > 0
                || ResponseDataAddressNotEqualCount > 0
                || BytesReceivedInCommunicationStateStartCount > 0
                || BytesReceivedInCommunicationStateSendFrameCount > 0
                || BytesReceivedInCommunicationStateDataResponseReceivedCount > 0
                || ExceptionCount > 0
                || NakcReceivedCount > 0
                || AckTimeoutCount > 0
                || DataTimeoutCount > 0;
        }

        public object Clone()
        {
            return MemberwiseClone();
        }

        internal void Reset()
        {
            // ... ?
        }
    }
    public CommunicationErrorsDetailsType CommunicationErrorsDetails = new CommunicationErrorsDetailsType();

    ...
    // Other nested classes
    ...
}

How can I achieve Reset() without having to recreate a new instance and without having to reset manually all members that can be of different types ?

All members are simple types (not classes).

Furthermore, I cannot change the structure of all classes of same type because we have several years of code structured like this.

Thank you for your help. Regards


Solution

  • Using Reflexion you can achieve what you want and with the help of DefaultExpression Class

    internal void Reset()
    {
        // Retrieves only the fields of this Class
        var bindingFlags = BindingFlags.Instance
                           | BindingFlags.NonPublic
                           | BindingFlags.Public;
        List<FieldInfo> members = this.GetType()
                                      .GetFields(bindingFlags)
                                      .Where(f => f.MemberType == MemberTypes.Field)
                                      .Where(value => value != null)
                                      .ToList();
    
        // Set all fields to its default type value
        for (int i = 0; i < members.Count(); i++)
        {
            // This expression represents the default value of a type
            // (0 for integer, null for a string, etc.)
            Expression defaultExpr = Expression.Default(typeof(byte));
            // The following statement first creates an expression tree,
            // then compiles it, and then executes it.
            var defaultValue = Expression.Lambda<Func<byte>>(defaultExpr).Compile()();
            // Set the default value
            members[i].SetValue(this, defaultValue);
        }
    }