Home > Blockchain >  Modifying an Existing Method to handle another type of class - Best Practice Recommendations
Modifying an Existing Method to handle another type of class - Best Practice Recommendations

Time:07-28

Knowledge level: I am a new C# programmer and this is the 1st time I have written object oriented code in about 6 yrs.

Context: My program reads information about individual equipment (Motors) from an excel document, performs some operations/conversion on the data, converts the data to a different class type, and then writes the new class information to a database.

I want to expand the existing method to allow for the user to pass in a different class of data. Currently it only handles information passed in as the custom excel class. I want to expand it to also allow for the user to pass in another class type, with different but similar parameters.

The core concept of my question here is in regards to the best practice for writing methods that can handle multiple different, but similar, classes.

I thought of a few ways of modifying my existing method to be able to be executed on two different, but similar class types.

  1. Two methods. One for each class. The fields are similar in each class but different names. Which is the fundamental challenge of this question.
  2. Same method but with several Ifs - seems like a poor approach
  3. Merge Excel Class and New class in question into a common class. Have the method operate on only the common class

Additional clarifying information:
If you are wondering why the classes are similar in terms of content stored, but different in terms of field names
*Excel class reads equipment info from excel.
*The new class I am trying to support is populated by reading from a database. The class has all the same fields that the database uses (both names and quantities).
*I need to perform operations on both of these custom classes to convert the information stored in either of those classes to a 3rd custom class, which is based off a separate database than the 2nd class.

The Code: I dont know how to do what I am trying to accomplish because of the foreach processing. I need to loop through both types at the same time. Currently setup to only work with DistQuery_Excel. IDK how to include the other class here...

        var DistQuery_Excel =
                from motor in motor_Excel
                orderby motor.MotorName //alpha order by motor name
                group motor by motor.MotorDist; //string
        var DistQuery_TEI =
                from motor in motor_TEI
                orderby motor.USER_TAG //alpha order by motor name
                group motor by motor.Distribution_Equipment; //string
        
        foreach (var distGroup in DistQuery_Excel) //for each Distribution Equipment group
        {
            int cirInc = 1; //if you need to make more circuits
            //query circuits_DM for total num of circuits for that dist
            DM_DistEquip dist = distLookupObj(distEquip_DM, distGroup.Key); //Get distEquip Obj from List of DM dist equip by looking up Pnl Name, return DM_DistEquip obj.
            int dist_Num = dist.ixPanel; //get primary key for the panel
            int numOfDevices = distGroup.Count(); //get number of equips for this dist
            List<DMCircuit> circuits_Per_Dist = circuits_Avail.Where(cir => cir.ixPanel == dist_Num).OrderBy(cir => cir.iCirNum).ToList(); //Get available circuits for this Dist Equip. Sort numerically

            foreach (var motor in distGroup)
            {
                DMMotor motorEx = ex_Load(motor.getName()); //check if motor exists in DM equipList_DM. Returns DM_Motor if found.
                //EXISTING MOTOR
                if (motorEx is not null) //if not null, is existing motor in DM. Update load information (HP, KVA, Load Factor)
                {
                    motorEx.LT_HP_1 = Convert.ToString(motor.MotorHP); //HP
                    motorEx.LT_CON_1 = motor.MotorKVA; //KVA
                    //TODO: update LT_FAC_1 if load type has changed
                    //TODO: update Voltage/Phase
                    if (circuits_Per_Dist.Any()) //if circuits still available
                    {
                        motorEx.ixCircuit1 = circuits_Per_Dist[0].ixCircuit; //assign to next circuit available via circuit Primary ID.
                        UpdateDM_Circuit(motorEx.EQU_CALLOUT, distGroup.Key   "-"   circuits_Per_Dist[0].iCirNum, motorEx.LT_CON_1, circuits_Per_Dist[0].ixCircuit, DMpath); //Update Circuits Available. Will push this back out to TblCircuit
                        circuits_Per_Dist.RemoveAt(0); //remove the circuit from availble list
                    }//end of if
                    else //No circuits left, must add them
                    {
                        motorEx.ixCircuit1 = InsertDM_Circuit(motorEx.EQU_CALLOUT, distGroup.Key   "-"   (dist.iTaps   cirInc), motorEx.LT_CON_1, dist_Num, dist.iTaps   cirInc, DMpath); //create blank entries within tblCircuit
                        cirInc  ;
                    }//end of else
                    equipList_EX.Add(motorEx); //Add motor to list. Will combine with equipList_NEW. Will push back out to tblEquL
                }//end of if
                 //NEW MOTOR
                else //is new load
                {
                    DMMotor motorNew = new DMMotor().Excel2DM(motor); //convert excel motor data to DM, assign DM motor properties
                    if (circuits_Per_Dist.Any())
                    {
                        motorNew.ixCircuit1 = circuits_Per_Dist[0].ixCircuit; //assign to next circuit available via circuit Primary ID.
                        UpdateDM_Circuit(motorNew.EQU_CALLOUT, distGroup.Key   "-"   circuits_Per_Dist[0].iCirNum, motorNew.LT_CON_1, circuits_Per_Dist[0].ixCircuit, DMpath);
                        circuits_Per_Dist.RemoveAt(0); //remove the circuit from availble list
                    }//end of if
                    else
                    {
                        motorNew.ixCircuit1 = InsertDM_Circuit(motorNew.EQU_CALLOUT, distGroup.Key   "-"   (dist.iTaps   cirInc), motorNew.LT_CON_1, dist_Num, dist.iTaps   cirInc, DMpath); //create blank entries within tblCircuit
                        cirInc  ;
                    }//end of else
                    equipList_NEW.Add(motorNew); //add motor to the list.  Will combine with equipList_EX. Will push back out to tblEquL
                }//end of else
            }//end of foreach
        }//end of foreach

CodePudding user response:

I ended up converting my two custom classes to the 3rd class by creating methods within the 3rd class for creating a new instance by mapping/converting the other class object variables.

CodePudding user response:

This is what I had in mind. Firstly we create an interface:

public interface IMyInterface
{
    string Name { get; set; }
    DateTime CreatedOn { get; set; }
    bool Valid { get; set; }
    string getName();
}

Next we create two classes that implement this interface:

public class Class1 : IMyInterface
{
    public string Name { get; set; }
    public DateTime CreatedOn { get; set; }
    public bool Valid { get; set; }
    public string getName()
    {
        return "Class1Name is "   Name;
    }
    public decimal SpecialValue { get; set; }
}

and:

public class Class2 : IMyInterface
{
    public string Name { get; set; }
    public DateTime CreatedOn { get; set; }
    public bool Valid { get; set; }
    public string getName()
    {
        return "Class2Name is "   Name;
    }
    public decimal SpecialValue { get; set; }
}

Now we can create two Lists, one of each class:

var class1s = new List<Class1>
{
    new Class1{ Name = "Article1",
                CreatedOn = new DateTime (2022,5,8),
                SpecialValue = 62.5M,
                Valid = false},
    new Class1{ Name = "Article2",
                CreatedOn = new DateTime (2022,7,19),
                SpecialValue = 46.1M,
                Valid = true}
};
var class2s = new List<Class2>
{
    new Class2{ Name = "Article3",
                CreatedOn = new DateTime (2022,2,2),
                SpecialValue = 18.5M,
                Valid = true},
    new Class2{ Name = "Article4",
                CreatedOn = new DateTime (2022,11,27),
                SpecialValue = 19.9M,
                Valid = false}
};

Next comes the clever bit. We combine the two lists into a new List of type IMyInterface (just one line of code):

var merged = class1s.Concat<IMyInterface>(class2s).ToList();

Note the Concat<IMyInterface>. That effectively tells the compiler to join the two lists, but only insofar as their respective implementations of IMyInterface.

Finally we can loop through this list:

foreach (var m in merged)
{
    string name = m.getName();
    bool valid = m.Valid;
    decimal val = m.SpecialValue;  //compiler error here
}

I have deliberately left a compiler error here: SpecialValue is not accessible. Why? Both classes have a SpecialValue of the same type. However this property is not in the interface. Within our foreach loop on the merged list, we only have access to those properties and methods that are defined in the interface.

  • Related