0

I have a model class as following which implements an interface;

public class EngTrModel : IWordModel
    {
        public string Word { get; set; }
        public string Translation { get; set; }
        public string WordPair
        {
            get
            {
                return $"{Word}->{Translation}";
            }
        }
    }

I have a processor class which is responsible for connecting to a Sqlite database and gets all rows as following;

public class SqliteDataAccess : IDataAccess
{
    public static string LoadConnectionString(string id = "Default")
    {
        return ConfigurationManager.ConnectionStrings[id].ConnectionString;
    }
    public static List<EngTrModel> LoadDatabase()
    {
        using (IDbConnection conn = new SQLiteConnection(LoadConnectionString()))
        {
            var output = conn.Query<EngTrModel>("Select * from Words", new DynamicParameters());
            return output.ToList();
        }
    }
}

In my WPF form code, when I click the 'Load Records' button it works fine and loads the table rows into a listbox as following;

private void loadFromDatabase_Click(object sender, RoutedEventArgs e)
{
    LoadFromDatabase(SqliteDataAccess.LoadDatabase());
}

private void LoadFromDatabase(List<EngTrModel> words)
{
    WordsListBox.ItemsSource = null;
    WordsListBox.ItemsSource = words;
    WordsListBox.DisplayMemberPath = "WordPair";
}

In the future when I expand my application to support other languages also, for example when I need to add EngFrModel which implements IWordModel interface into my application, I want to be able to use 'LoadFromDatabase' method without changing anything(Open Closed Principle). I've made a few attempts but none of them working; For example, I want to use following method not with hard-coded values and give this method the functionality to work with different kind of models and database tables;

public static List<IWordModel> LoadDatabase(string table)
{
    using (IDbConnection conn = new SQLiteConnection(LoadConnectionString()))
    {
        var output = conn.Query<IWordModel>($"Select * from {table}", new DynamicParameters());
        return output.ToList();
    }
}

Then I made following changes;

private void loadFromDatabase_Click(object sender, RoutedEventArgs e)
{
    LoadFromDatabase(SqliteDataAccess.LoadDatabase("Words"));
}

private void LoadFromDatabase(List<IWordModel> words)
{
    WordsListBox.ItemsSource = null;
    //WordsListBox.ItemsSource = DataAccess.LoadDatabase();
    WordsListBox.ItemsSource = words;
    WordsListBox.DisplayMemberPath = "WordPair";
}

The code can be compiled without error but it gives System.ArgumentException: 'Invalid type owner for DynamicMethod.' error in the following line of code;

 var output = conn.Query<IWordModel>($"Select * from {table}", new DynamicParameters());
zalky
  • 659
  • 1
  • 7
  • 12
  • Not sure what that error is since you didn't give the full exception message, but at a guess, you are telling the framework to make instances of `IWordModel` and it has no way to do that, the `Query` method needs a concrete class that it can instantiate. – DavidG Mar 06 '21 at 21:41
  • That's right it only accepts a concrete class, any idea how to create the structure to use these methods with different types of tables? – zalky Mar 06 '21 at 21:44
  • Not really sure what you mean, you could make `LoadDatabase` generic but with a constraint to make sure it's a `IWordModel` and `class`? – DavidG Mar 06 '21 at 21:53
  • I want to be able to use 'LoadDatabase' method for different kind of model classes, for example for 'EngTrModel' and 'EngFrModel' without changing the method implementation. – zalky Mar 06 '21 at 21:57
  • 1
    Then the generic option would work, you just need a way to associate the generic type with the table name, perhaps an attribute or a property in the interface. – DavidG Mar 06 '21 at 21:58
  • That seems like the answer but I'm having trouble implementing this approach since the beginning, is it possible for you to provide an example of this approach? – zalky Mar 06 '21 at 22:05
  • Did you mean something like this? https://dotnetfiddle.net/n8On9H – DavidG Mar 06 '21 at 22:21

0 Answers0