Список<CustomClass> отправляется как список<T>; как получить свойства?

У меня есть этот кусок кода

 public class Ticket
    {
        public string strArticleID { get; set; }
        public string strArticleDescription { get; set; }
        public decimal decArticlePrice { get; set; }
        public decimal decArticleVAT { get; set; }
        public decimal decArticuleNetPrice { get; set; }
        public decimal decArticleDiscount { get; set; }
        public decimal decArticleQuantity { get; set; }

    }
    public static List<Ticket> _lstCurrentTicket = new List<Ticket>();

Что я хочу, чтобы отправить во внешнюю DLL, чтобы получить все строки в _lstCurrentTicket, чтобы распечатать билет через

for (int i = 0; i < dataGridView1.Rows.Count; i++)
        {
            Ticket ticket = new Ticket();

            string strRefID = this.dataGridView1.Rows[i].Cells[0].Value.ToString();
            string strDescription = this.dataGridView1.Rows[i].Cells[1].Value.ToString();
            decimal decQuantity = (decimal)this.dataGridView1.Rows[i].Cells[2].Value;
            decimal decUPrice = (decimal)this.dataGridView1.Rows[i].Cells[3].Value;
            decimal decDiscount = Convert.ToDecimal(this.dataGridView1.Rows[i].Cells[4].Value.ToString().Substring(0, this.dataGridView1.Rows[i].Cells[4].Value.ToString().Length - 1));
            decimal decVAT = Convert.ToDecimal(this.dataGridView1.Rows[i].Cells[5].Value.ToString().Substring(0, this.dataGridView1.Rows[i].Cells[5].Value.ToString().Length - 1));
            decimal decGPrice = (decimal)this.dataGridView1.Rows[i].Cells[6].Value;


            ticket.strArticleID = strRefID;
            ticket.strArticleDescription = strDescription;
            ticket.decArticlePrice = decUPrice;
            ticket.decArticleVAT = decVAT;
            ticket.decArticuleNetPrice = decGPrice;
            ticket.decArticleDiscount = decDiscount;
            ticket.decArticleQuantity = decQuantity;

            _lstCurrentTicket.Add(ticket);
        }


 TicketPrinting tktPrint = new TicketPrinting ();
 //Ticket and copies
 tktPrint.PrintTicketFromList(_lstCurrentTicket, 2);

Поскольку это внешняя DLL, я подумал, что самый простой способ работы с ней в целевой DLL был

 public void PrintTicketFromList<T>(List<T> lstArticles, short intCopies)
    {            
        foreach (var prop in lstArticles.GetType().GetProperties())
        {

            if (prop.Name == "Item")
            {
                //Copy external list to local class for printing

            }
        }...

Но я застрял там. Как я могу перебрать каждое свойство и значение из каждого исходного класса в списке, чтобы я мог скопировать его? Если я создаю точку останова, я вижу, что поля и значения передаются правильно, но я не понимаю, как получить к ним доступ, поэтому я могу сделать что-то вроде создания локального класса точно так же, как оригинал, и клонировать список (и если я попробую это сделать) скажет, что локальный список (Ticket) и переданный список (T) не одного типа).

Или как я могу скопировать его, если я создаю точный класс в целевой и сделать что-то вроде

public void PrintTicketFromList(object lstArticles, short intCopies)
    {
        List<TargetDLLTicket> lst =((List<TargetDLLTicket>)lstArticles).ToList(); }

Какие-нибудь мысли?

3 ответа

Решение

Если возможно, старайтесь избегать размышлений, как это делает Игорь в своем ответе.

Но если вы действительно хотите использовать отражение, вы в настоящее время не осматриваете предмет, а список предметов.

Вы должны попробовать что-то вроде (писать это по памяти):

public void PrintTicketFromList<T>(List<T> lstArticles, short intCopies)
{   
    foreach (var item in lstArticles)
    {
        foreach (var prop in typeof(T).GetProperties())
        {
            var value = prop.getValue(item);
        }
    }
}

Похоже, у вас есть проблема круговой зависимости. Вам необходимо переместить типы, которые вы отправляете в функцию печати, в общую сборку (новый проект), на которую ссылаются как вызывающий проект, так и ваш проект печати. Тогда оба проекта могут получить доступ к этому общему типу.

Примечание о вашем дизайне. То, как вы делаете это, вероятно, не очень хорошо для начала, таким образом, ваша ошибка. Реальная функция принтера не должна знать ничего о передаваемых типах. Хорошее практическое правило - попытаться сделать ваш код как можно более слабосвязанным. Лучшая идея - создать интерфейс, который позаботится о записи на холст принтера (или что-то подобное, вы не предоставили свой код принтера, так что это предположение), и функция принтера может вызвать этот метод для входящего объекта. Метод принтера должен также принимать этот интерфейс только в качестве параметра. Это основано на шаблоне посетителя. Вот пример.

public interface IPrintable {
   void WriteToPrinter(PrinterCanvas canvas);
}

public class Printer {
   public void Print(IPrintable somethingToPrint) {
      var canvas = getCanvas();
      somethingToPrint.WriteToPrinter(canvas);
   }
}

Вместо List<T> создать интерфейс, например ITicket и принять List<ITicket>, С помощью List<T> как универсальный, когда вы знаете, что вы можете работать только с чем-то, что является билетом, создает ненужный широкий диапазон потенциальных входов. Использование интерфейса позволяет вам не беспокоиться о конкретной реализации, а вместо этого получить только то, чем занимается ваша dll, контракт.

Вы можете поместить интерфейс в одно из двух мест: либо другую внешнюю общую сборку, на которую ссылаются обе ваши сборки, либо поместить интерфейс в свою сборку, которая имеет логику печати билетов. Ваш класс Ticket может затем реализовать интерфейс.

Пример того, как это может выглядеть:

public interface ITicket
{
   //properties and methods you want to have all implementations to contain.
}

public class Ticket : ITicket
{
}

public class LastTicket :ITicket
{
}

public void PrintTicketFromList(List<ITicket> lstArticles, short intCopies)
{
}
Другие вопросы по тегам