Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

I had a loop through object Process, each process instance can be of a different

ID: 639818 • Letter: I

Question

I had a loop through object Process, each process instance can be of a different type, derived from Process base class (e.g.: Process1, Process2,...). Each derived type of Process has different properties. For instance: some Processes are indexable, this is notified by IsIndexable flag. When a Process is indexable has some additional properties (for instance: AccessDate) that non-indexable process doesn't have. Now I have to cycle on each Process in request.Process (remember indexable Processes are different from others)

foreach (Process process in request.Processes)
{
     if(process.getType().Name.Equals("Process1")) // indexable process
     {
         ((Process1)process).Name = "aName";
         ((Process1)process).AccessDate = DateTime.Now;
     }
     else if(process.getType().Name.Equals("Process2")) // non indexable process
     {
         ((Process2)process).Name = "anotherNane";
         //compile error - AccessDate don't exist for type Process2
         //((Process2)process).AccessDate = DateTime.Now;        
     }
}
Since I hate that cascading if I have rewritten using interface:

IProcessable processableImpl = // some Unity stuff based on request type
foreach (Process process in request.Processes)
{
     processableImpl.fillTheRightProperties(process);
}
processableImpl is injected in a different manner based on the request.Type. At this point fillTherRightProperties method will do the work for me on the current process.

public interface IProcessable
{
    void fillTheRightProperties(Process process);
}

public class IndexableProcess : IProcessable
{
    void fillTheRightProperties(Process process){
        Process1 process1 = process as Process1;

        if(process1==null) throw MyException("Process1 expected");

        process1.Name = "aName";
        process1.AccessDate = DateTime.Now;
    }
}

public class NonIndexableProcess : IProcessable
{
    void fillTheRightProperties(Process process){
        Process2 process2 = process as Process2;

        if(process2==null) throw MyException("Process2 expected");

        process2.Name = "aName";
    }
}
This is more beautiful than a cascading if but I feel still not as beautiful as it could be. I feel a violation of responsability, since the concrete class edit process property elsewhere, and I'm afraid to read this code a week after.

Explanation / Answer

Below is an example using an interface and two implementations in a console application:

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var processes = new List<IProcessable>();
processes.Add(new Process1());
processes.Add(new Process2());

foreach (IProcessable item in processes)
{
item.FillTheRightProperties();
}

Console.WriteLine();
Console.WriteLine("Press Enter/Return to exit...");
Console.ReadLine();
}
}

interface IProcessable
{
void FillTheRightProperties();
}

class Process1 : IProcessable
{
public string Name { get; set; }
public DateTime AccessDate { get; set; }

public void FillTheRightProperties()
{
this.Name = "aName";
this.AccessDate = DateTime.Now;

Console.WriteLine("Properties filled: {0}, {1}", this.Name, this.AccessDate);
}
}

class Process2 : IProcessable
{
public string Name { get; set; }

public void FillTheRightProperties()
{
this.Name = "aName";

Console.WriteLine("Properties filled: {0}", this.Name);
}
}
}
The key line is in the foreach where we use the interface rather than casting to a concrete class.

To map this to your example request.Processes would be a List<IProcessItem> meaning we can guarantee that the DoSomething() method exists, and there is no need to cast to a concrete class.

The base class can also be used, but it's purpose would be to hold common code only.