Список<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)
{
}