Good day, faced with such a problem. There is an abstract ViewModel class that contains the logic for adding data to the collection for display in the GUI.

 public abstract class ViewModel { public ObservableCollection<IModel> Data { get; set; } protected abstract IModel createObject(SqlDataReader reader); protected void selectData(string query) { // ... // Π›ΠΎΠ³ΠΈΠΊΠ° получСния reader // ... IModel item = this.createObject(reader); this.Data.Add(item); } } 

There are also classes of models, all of them implement the IModel interface, I will not give the code, there is no need for it. The class implementing ViewModel looks like this:

 public class UsersViewModel : ViewModel { public UsersViewModel() { string query = "SELECT TOP 300 * FROM users ORDER BY reputation DESC"; this.selectData(query); } protected override IModel createObject(SqlDataReader reader) { return new User(reader); } } 

The problem is actually in the createObject method. In all subclasses, it does one single thing: it returns an instance of the model class. I would like to get rid of him. And to make it so that in the abstract class ViewModel the selectData method itself created the model object it needed, and which one it would learn from the subclass. The method should look something like this:

 protected void selectData(string query) { // Π›ΠΎΠ³ΠΈΠΊΠ° получСния reader IModel item = new Π’ΠΈΠΏ_МодСли_ΠΈΠ·_подкласса(reader); this.Data.Add(item); } 

It seems to me that the problem can be solved with the help of generalizations, but I do not know how. Or create a property in the subclass that will specify which particular implementation of the IModel interface IModel be used. How do I implement this? Thank you in advance.

  • class parent should not know about the class heir. Therefore, for reasons of readability, it is better to leave as is. Although maybe I did not correctly understand the class "User" makes you doubt (where it came from and why). - Valera Kvip
  • Here in PHP, for example, there is later static binding, you can write new static () there, but if it were the same in c #, this is a bit wrong. - Klym

1 answer 1

Well, for example, one of the methods is:

 public abstract class ViewModelImpl<T> : ViewModel where T : IModel { protected void selectData(string query) { // Π›ΠΎΠ³ΠΈΠΊΠ° получСния reader IModel item = (T)Activator.CreateInstance(typeof(T), reader); this.Data.Add(item); } } 

Well and inherit specific classes from ViewModelImpl<T> with the necessary type T

(If the constructor T had no parameters, one could do without reflection.)


For better readability, you can take out the method:

  private T CreateModelItem(SqlDataReader reader) { return (T)Activator.CreateInstance(typeof(T), reader); } protected void selectData(string query) { // Π›ΠΎΠ³ΠΈΠΊΠ° получСния reader IModel item = CreateModelItem(reader); this.Data.Add(item); } 

However, you already have this auxiliary method, it is called createObject .

  • And now I begin to wander the opinion of the first commentator. Readability in this case greatly decreases. - Klym
  • one
    @Klym: Yes, reflexion is usually not readable. Completed the answer. - VladD
  • Well, but now this helper method createObject is not in subclasses, but right in the abstract, that's what I wanted. Thank. - Klym
  • @Klym: Please! - VladD