Search code examples
c#inheritanceinterfacedto

C# DTO with calculated property


I have some DTOs that need save to the redis, and I want all of them have a property or method to generate key of redis.

public class Product
{
   public string Name {get; set;}
   public string Type {get; set;}

   // Use Property (Maybe Inherit a base class or interface)
   public string CacheKey
   {
      get
      {
         return Type + "_" + Name;
      }
   }

   // User Method (Maybe Inherit a base class or interface)
   public string GetCacheKey()
   {
      return Type + "_" + Name;
   }
}

Or... I should not add them to DTO, but I want all the DTOs that need save to redis were must have a key, and each of Key were generate by the property of itself.

Can someone give me some suggestion?


Solution

  • Observing the Open-Closed Principle of the SOLID principles

    You should not change the established purpose of a DTO (As @GlennvanAcker said a DTO does not have logic).

    However, we can give it an extension method... Which is what I suggest.

        public static class ProductExtensions
        {
            public static string CacheKey(this Product product)
            {
                return product.Type + "_" + product.Name;
            }
        }
    

    @HansKesting pointed out that I didn't show how to make this work for classes other than Product...

    This would require us to extend the base class or interface. If this method is to be applied to multiple classes; the compiler needs to know that the class has the required properties(Type and Name):

    e.g.

    // I'm not calling this interface IDto because I am not assuming that all DTOs have these properties.
    public interface IDtoWithTypeAndName
    {
        public string Type { get; set; }
        public string Name { get; set; }
    }
    
    public static class DtoExtensions
    {
        public static string CacheKey(this IDtoWithTypeAndName dto)
        {
            return dto.Type + "_" + dto.Name;
        }
    }
    public class Product : IDtoWithTypeAndName
    {
        public string Type { get; set; }
        public string Name { get; set; }
    }