dotNetTips.Spargine icon indicating copy to clipboard operation
dotNetTips.Spargine copied to clipboard

PreserveAttribute: Proposal

Open RealDotNetDave opened this issue 2 years ago • 1 comments

When I spend time reviewing code for issues, I use the indicator in Visual Studio to tell me if that variable, method, or class is in use. There are many reasons that this number might be 0 but the code is still in use either by:

  • Object is set via dependency Injection
  • Method implemented due to definition in an interface
  • Overriding a method from a base class.

Proposal

To make it easier to look at the code and know that the code needs to be preserved due to one of these reasons, I propose adding a new attribute to dotNetTips.Spargine.6.Core project. The proposed name is: PreserveAttribute.

I'm proposing this attribute to make it easier and faster to review code. ALL suggestions are welcome! Please add a comment.

This is the code for the attribute:

/// <summary>
/// PreserveAttribute. This class cannot be inherited.
/// Implements the <see cref="Attribute" />
/// </summary>
/// <seealso cref="Attribute" />
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface | 
 AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | 
 AttributeTargets.Event | AttributeTargets.Delegate, Inherited = false)]
public sealed class PreserveAttribute : Attribute
{
	/// <summary>
	/// Initializes a new instance of the <see cref="PreserveAttribute"/> class.
	/// </summary>
	/// <param name="preserveReason">The preserve reason.</param>
	/// <param name="reason">The reason.</param>
	/// <param name="createdOn">Created on.</param>
	/// <param name="createdBy">Created by.</param>
	/// <exception cref="ArgumentNullException">createdBy</exception>
	/// <exception cref="ArgumentNullException">reason</exception>
	public PreserveAttribute(PreserveReason preserveReason, string reason, string createdOn, string createdBy)
	{
		this.CreatedBy = createdBy ?? throw new ArgumentNullException(nameof(createdBy));
		this.PreserveReason = preserveReason;
		this.Reason = reason ?? throw new ArgumentNullException(nameof(reason));

		if (string.IsNullOrEmpty(createdOn) is false && DateTimeOffset.TryParse(createdOn, out var createdDate))
		{
			this.CreatedOn = createdDate;
		}
	}

	/// <summary>
	/// Initializes a new instance of the <see cref="PreserveAttribute"/> class.
	/// </summary>
	/// <param name="reason">The reason.</param>
	/// <param name="createdOn">Created on.</param>
	/// <param name="createdBy">Created by.</param>
	/// <exception cref="ArgumentNullException">createdBy</exception>
	/// <exception cref="ArgumentNullException">reason</exception>
	public PreserveAttribute(string reason, string createdOn, string createdBy)
		:this(PreserveReason.None,reason,createdOn,createdBy)
	{
	}

	/// <summary>
	/// Initializes a new instance of the <see cref="PreserveAttribute"/> class.
	/// </summary>
	/// <param name="reason">The reason.</param>
	public PreserveAttribute(string reason)
	: this(PreserveReason.None, reason, string.Empty, string.Empty)
	{
	}

	/// <summary>
	/// Gets or sets the modified by.
	/// </summary>
	/// <value>The modified by.</value>
	public string CreatedBy { get; }

	/// <summary>
	/// Gets the created on date.
	/// </summary>
	/// <value>The created on.</value>
	public DateTimeOffset CreatedOn { get; }

	/// <summary>
	/// Gets the <see cref=" PreserveReason" />.
	/// </summary>
	/// <value>The reason.</value>
	public PreserveReason PreserveReason { get; }

	/// <summary>
	/// Gets the reason description.
	/// </summary>
	/// <value>The reason description.</value>
	public string Reason { get; }
}

/// <summary>
/// Enum PreserveReason
/// </summary>
public enum PreserveReason
{
	/// <summary>
	/// None selected
	/// </summary>
	None = 0,

	/// <summary>
	/// Oject is injected via DI.
	/// </summary>
	ObjectInjected = 1,

	/// <summary>
	/// Method is defined due to an interface
	/// </summary>
	MethodFromInterface = 4,

	/// <summary>
	/// Method overrides a method from a base class.
	/// </summary>
	MethodOverride = 8,

	/// <summary>
	/// Other - Make sure to set ReasonDescription.
	/// </summary>
	Other = 1000,
}

Example

Here is an example on how to use it:

[Preserve(preserveReason: PreserveReason.MethodOverride, reason: "Used by serialization.", 
 createdOn: "01/07/2023", createdBy: "David McCarter")]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
	base.GetObjectData(info, context);

	info.AddValue(nameof(this.UserMessage), this.UserMessage);
}

RealDotNetDave avatar Feb 08 '23 00:02 RealDotNetDave

Hi Dave,

try to build the project but got this error, could you please provide any pointers?

image

leolinnzgit avatar Mar 19 '23 01:03 leolinnzgit