c# реализовать generi c of T, чтобы избежать лишних логик c и иметь более чистый код - PullRequest
0 голосов
/ 18 апреля 2020

У меня есть следующий код, использующий C# Winforms DataGridView.

 // METHOD TO PASTE DATA INTO GRID
 private void btnPasteCatalog_Click(object sender, EventArgs e)
        {
            BindingSource source = (BindingSource)gridCatalog.DataSource;
            source.ListChanged -= Source_ListChanged;

            IBindingList dataSource = null;

            BindingList<Models.SetupArea> areaList = null;
            BindingList<Models.SetupDepartment> deptList = null;

            if (source.DataSource is BindingList<Models.SetupArea>)
            {
                dataSource = (BindingList<Models.SetupArea>)source.DataSource;
            }
            else if(source.DataSource is BindingList<Models.SetupDepartment>)
            {
                dataSource = (BindingList<Models.SetupDepartment>)source.DataSource;
            }

            DataObject o = (DataObject)Clipboard.GetDataObject();
            if (o.GetDataPresent(DataFormats.StringFormat))
            {
                string[] pastedRows = Regex.Split(o.GetData(DataFormats.StringFormat).ToString().TrimEnd("\r\n".ToCharArray()), "\r");
                int j = 0;
                try { j = gridCatalog.CurrentRow.Index; } catch { }

                foreach (string pastedRow in pastedRows)
                {
                    if (source.DataSource is BindingList<Models.SetupArea>)
                    {
                        // i had to use this instead of dataSource because if not I get error
                        areaList = (BindingList<Models.SetupArea>)source.DataSource;

                        areaList.Add(new Models.SetupArea()
                        {
                            Description = pastedRow.Split(new char[] { '\t' })[0]
                        });
                    }
                    else if (source.DataSource is BindingList<Models.SetupDepartment>)
                    {
                        // i had to use this instead of dataSource because if not I get error
                        deptList = (BindingList<Models.SetupDepartment>)source.DataSource;

                        deptList.Add(new Models.SetupDepartment()
                        {
                            Description = pastedRow.Split(new char[] { '\t' })[0]
                        });
                    }


                    j++;
                }


                // HERE IS WANT TO PASS GENERIC OF T
                // save to database
                if (source.DataSource is BindingList<Models.SetupArea>)
                {
                    // This is wrong it should be only Models.SetupArea
                    SaveCatalog<BindingList<Models.SetupArea>>(areaList);
                }

                // save to database
                if (source.DataSource is BindingList<Models.SetupDepartment>)
                {
                    // This is wrong it should be only Models.SetupArea
                    SaveCatalog<BindingList<Models.SetupDepartment>>(deptList);
                }

                source.ListChanged += Source_ListChanged;
            }
        }

        // SAVE DATA INTO LITEDB DATABASE
        private void SaveCatalog<T>(T data)
        {
            // Open database (or create if doesn't exist)
            using (var db = new LiteDatabase(@"SoftCATCovid19.db"))
            {
                string tableName = null;

                switch (cboCatalogs.Text.ToLower())
                {
                    case "area":
                        tableName = "setup_area";

                        break;
                    case "department":
                        tableName = "setup_department";

                        break;
                }

                // T should be either Models.SetupArea or Models.SetupDepartment
                // right now im receiving BindingList<Models.SetupDepartment> and this breaks the code.


                var col = db.GetCollection<T>(tableName);

                var records = data as BindingList<T>;

                col.Insert(data);

            }
        }

Я хотел бы использовать Generi c вместо T вместо того, чтобы делать все мои IF logi c, потому что в конце я здесь может быть более 10 каталогов, и код будет огромным и не обслуживаемым.

Более важно то, что я использую BindingList, поэтому для передачи Generi c T в метод SaveCatalog, который у меня есть передать тип класса, такой как Model.SetupArea или Model.SetupDepartment, и что параметр также имеет этот тип, в противном случае код нарушается.

Ответы [ 2 ]

0 голосов
/ 18 апреля 2020

Может быть, вам просто нужно переопределить SaveCatalog следующим образом:

// SAVE DATA INTO LITEDB DATABASE
private void SaveCatalog<T>(BindingList<T> data)
{
  // Open database (or create if doesn't exist)
  using (var db = new LiteDatabase(@"SoftCATCovid19.db"))
  {
    string tableName = GetTableName(data);

    var col = db.GetCollection<T>(tableName);
    foreach(var entry in data)
    {
      col.Insert(entry);
    }

  }
}

string GetTableName<T>(BindingList<T> data)
{
  switch (data)
  {
    case BindingList<Models.SetupArea> _:
      return "setup_area";
    case BindingList<Models.SetupDepartment> _:
      return "setup_department";

    default:
      return null;
  }
}

Тогда вам больше не нужно делать if и только звоните SaveCatalog следующим образом:

SaveCatalog<Models.SetupArea>(areaList);

SaveCatalog<Models.SetupDepartment>(deptList);
0 голосов
/ 18 апреля 2020

Я бы хотел использовать Generi c вместо T вместо того, чтобы делать все мои логи IF c, потому что в конце я мог бы иметь здесь более 10 каталогов, и код будет огромным и не подлежащим обслуживанию.

Для части IF вы должны использовать отражение с комбинацией генериков, чтобы сделать метод действительно обобщенным c way:

private static void AddBindingSource<T>(BindingSource source, string pastedRow)
{
    if (source.DataSource is BindingList<T> areaList)
    {
        var data = pastedRow.Split(new char[] { '\t' }).FirstOrDefault();
        areaList.Add((T)Activator.CreateInstance(typeof(T), data));
    }
}

Более важно то, что я использую BindingList, поэтому, чтобы передать Generi c T методу SaveCatalog, мне нужно передать тип класса, например Model.SetupArea или Model.SetupDepartment, и параметр также имеет этот тип, в противном случае код перерывы.

AddBindingSource<Models.SetupArea>(new BindingSource(), "test");

Надеюсь, это поможет))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...