Getting type of child class from parent class parameter in C #

I will have several “types” of the object, and I'm really not sure how best to retrieve / save these several types without separately saving / retrieving for each type.

My classes:

public class Evaluation {
  public int Id
  public string Comment
}

public class EvaluationType_1 : Evaluation {
  public string field
}

public class EvaluationType_1 : Evaluation {
  public string field
}

What I would like to do in my repository:

public interface IEvaluationRepository {
  public Evaluation getEvaluation(int id);
  public SaveEvaluation(Evaluation);
}

Inside the get / save methods:

// Save/get common fields
Id
Comments

// Get child type, perform switch
Type childType = ???
switch(childType) {
  // Set child-specific fields
}

Hope this makes sense. I would prefer not to add the "type" column, as I have this in another part of my database, and I don't like it very much.

UPDATE

Great comments, everyone - thank you very much. Here is additional information / questions for clarification, if necessary.

I like the idea of ​​using interfaces and generics, I really don’t understand how to include them in my repository template.

getEvaluation, , , . - - !

2

, , : P.

:        Id (PK)     

EvaluationType1
  Id (FK to Evaluations.Id)
  Field

EvaluationType1
  Id (FK to Evaluations.Id)
  Field

, getEvaluation(int id) , . , ? saveEvaluation, switch/function, , Type.

+3
6

public interface ISaveable {
   void SaveFields();
}

public abstract class Evaluation : ISaveable {
  public int Id
  public string Comment

  public virtual void SaveFields() {
     //Save ID and Comments
  }
}

public class EvaluationType_1 : Evaluation {
    public string field1

  public override void SaveFields() {
     //Save field1
     base.SaveFields();
  }

}

public class EvaluationType_2 : Evaluation {
   public string field2

  public override void SaveFields() {
     //Save field2
     base.SaveFields();
  }

}

ISaveable, List<ISaveable>, SaveFields , . , . .

: . , :

:

public interface IEvaluationRepository {
  public Evaluation getEvaluation(int id);
  public SaveEvaluation(Evaluation);
}

:

 public interface ISaveableRepository {
   public ISaveable getSavable(int id);
   public Save(ISaveable saveable);
 }

:

 public class SaveableEvaluationRepository : ISaveableRepository {
   public ISaveable getSavable(int id) {
       //Add your logic here to retrieve your evaluations, although I think that 
       //this logic would belong elsewhere, rather than the saveable interface.
   }

   public Save(ISaveable saveable) {
       saveable.SaveFields();
   }
 }
+4

, , , . .

EvaluationType_1 objOfEvalType1 = new EvaluationType_1();
Type childType = objOfEvalType1.GetType();

/ , , .

public class Evaluation {
  public int Id;
  public string Comment;

  //call this.GetType() anywhere you wish to get the type of the object.
  public Type MyType = this.GetType();
}
+1

, ORM .

public interface IEvaluationRepository<TEvaluation> 
{ 
  public TEvaluation getEvaluation(int id); 
  public SaveEvaluation(TEvaluation evaluation); 
} 

, EvaluationBase EvaluationBase:

public interface IEvaluationRepository<TEvaluation> where TEvaluation : EvaluationBase
...
public class SomeEvaluation : EvaluationBase
{
}

.

+1

Object.GetType - :

Type type = evaulation.GetType();

// Note that you can't switch on types

if (type == typeof(DerivedEvaluation1)) {
    // Perform custom operations        
}
else if (type == typeof(DerivedEvaluation2)) {
    // Perform custom operations
}

// Etc.
0

"" . , , - , is.

.

-, Save :

private static readonly Dictionary<Type,Action<Evaluation>> s_SaveFunctions =
    new Dictionary<Type,Action<Evaluation>>();

s_SaveFunctions[typeof(ChildA)] = SaveChildA;
s_SaveFunctions[typeof(ChildB)] = SaveChildB;
// .. and so on.

public SaveEvaluation( Evaluation eval )
{
   // .. common save code ...

   // cal the appropriately typed save logic...
   s_SaveFunctions[eval.GetType()]( eval );
}

private static void SaveChildA( Evaluation eval ) { ... }

private static void SaveChildB( Evaluation eval ) { ... }

.NET 4 dynamic :

public SaveEvaluation( Evaluation eval )
{
   // .. common save logic ..

   dynamic evalDyn = eval;

   SaveChild( evalDyn );
}

private void SaveChild( ChildA eval ) { ... }

private void SaveChild( ChildB eval ) { ... }

, SaveChild , . dynamic, SaveEvaluation, .

0

- , .

public class Evaluation
{
    public Int32 Id { get; set; }
    public String Comment { get; set; }

    public virtual void Save()
    {
        // Save the common information.
        this.SaveToDatabase(this.Id);
        this.SaveToDatabase(this.Comment);
    }

    private void SaveToDatabase(Object value)
    {
        // Left as an exercise for the reader... :D
    }
}

public class EvaluationType1 : Evaluation
{
    public String Foo { get; set; }

    public override void Save()
    {
        // Save the common information.
        base.Save();

        // Save the specific information here.
        this.SaveToDatabase(this.Foo);
    }
}


public class EvaluationType2 : Evaluation
{
    public String Bar { get; set; }

    public override void Save()
    {
        // Save the common information.
        base.Save();

        // Save the specific information here.
        this.SaveToDatabase(this.Bar);
    }
}

Perhaps you can also make an abstract abstract function. In addition, you should usually avoid making the fields publicly available - this can turn the code into a nightmare, and therefore I use properties in my example.

0
source

Source: https://habr.com/ru/post/1753358/


All Articles