Link to home
Start Free TrialLog in
Avatar of Misha
MishaFlag for Russian Federation

asked on

C# SOLID and best practices

Hello!
I need advice for SOLID principles and programming best practices.

I have two classes inherited from one main class. Objects of this classes are in List. I need beautifull solution to print information about this classes

Class Entity
class Entity
{
       
}

Open in new window


Class Person
sealed class Person : Entity
{
       internal FirstName {get; set;}
       internal LastName {get; set;}

       public override string ToString()
        {
            return $"FirstName ={FirstName } LastName  = {LastName } ";
        }
 }

Open in new window


Class Car
sealed class Car: Entity
{
       internal Name {get; set;}
       internal MaxSpeed {get; set;}

       public override string ToString()
        {
            return $"Name ={Name } MaxSpeed = {MaxSpeed } ";
        }
}

Open in new window


Class Writer
sealed class Writer
{
    internal void Write()
    {
        List<Entity> entities= new List<Entity>();
       // add some persons..
      // add some cars...
       StreamWriter writer = new StreamWriter("qwe.txt");
       foreach (Entity e in entities)
       {
            writer.WriteLine(e.ToString());
       }
    }
}

Open in new window


In real case there is complex logic in method  ToString. And some other objects are using in method ToString()
Avatar of it_saige
it_saige
Flag of United States of America image

You can have your base class override ToString() and then call a simple extension method to return the properties formatted however you want; e.g. -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace EE_Q29180515
{
    class Program
    {
        static void Main(string[] args)
        {
            var person = new Person { FirstName = "Bob", LastName = "Ross" };
            var car = new Car { Name = "FastCar", MaxSpeed = 220 };

            Console.WriteLine(person);
            Console.WriteLine(car);

            Console.ReadLine();
        }
    }

    class Entity
    {
        public override string ToString()
        {
            return $"{{ {this.GetPropertiesString()} }}";
        }
    }

    sealed class Person : Entity
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    sealed class Car : Entity
    {
        public string Name { get; set; }
        public int MaxSpeed { get; set; }
    }

    static class Extensions
    {
        public static string GetPropertiesString<T>(this T source)
        {
            return string.Join(", ", from property in source.GetType().GetProperties() select $"{property.Name}: {property.GetValueOrValues(source)}");
        }

        static string GetValueOrValues(this PropertyInfo property, object source)
        {
            var value = property.GetValue(source);
            if (ReferenceEquals(value, null))
            {
                return string.Empty;
            }
            else if (Equals(property.PropertyType, typeof(string)) && typeof(IEnumerable<>).IsAssignableFrom(property.PropertyType))
            {
                return $"{{ {string.Join(", ", from item in value as IEnumerable<object> select item)} }}";
            }
            else
            {
                return value.ToString();
            }
        }
    }
}

Open in new window

Produces the following output -User generated image-saige-
What problem are you trying to solve here. The code you already have will work. It will call ToString() on each of your derived classes, and output the correct info.
Avatar of Misha

ASKER

Thank you for response!

@it_saige
There is complex logic in each overriding method ToString(). There is no identical to all classes method to print each property.
If I use your solutin I should write something like this:
 public static string GetPropertiesString<T>(this T source)
        {
         if (source is Peson)
          {
            // print special logic for Peson
          }

         if (source is Car)
         {
            // print special logic for Car

          }
/// a lot of other classes
        }

Open in new window


I think it is not the best practices..

@Chris Stanyon
I want to find the best  solution. My overriding method ToString() have a complex logic. I think, it is not good to stay this method in classes, which are only  intended for storage data.

@All
I think there  should be other classes for print Person , Car and other objects.... May be..
And each implements interface for printing special object .... May be...
SOLUTION
Avatar of it_saige
it_saige
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Misha

ASKER

Thank you very mach!