List<CustomClass> 作为 List<T> 发送;如何获得属性?
List<CustomClass> sent as List<T>; how to get the properties?
我有这段代码
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
}
}...
但我被困在那里。如何迭代列表中每个 属性 和每个原始 class 的值以便复制它?如果我创建一个断点,我可以看到字段和值已正确传递,但我不知道如何访问它们,所以我可以做一些事情,比如创建一个与原始列表完全一样的本地 class 并克隆列表(和如果我尝试它会说本地列表(Ticket)和传递的列表(T)不是同一类型)。
或者如果我在目标中创建一个精确的 class 并执行类似
的操作,我该如何复制它
public void PrintTicketFromList(object lstArticles, short intCopies)
{
List<TargetDLLTicket> lst =((List<TargetDLLTicket>)lstArticles).ToList(); }
有什么想法吗?
听起来你遇到了循环依赖问题。您需要将发送到打印函数的类型移动到一个公共程序集(新项目),然后调用项目和打印项目都引用该程序集。然后两个项目都可以访问这个共享类型。
关于您的设计的注释。您处理此问题的方式可能一开始并不好,因此您的错误。实际的打印机函数不应该知道传入的类型的任何信息。一个好的经验法则是尝试使您的代码尽可能松散耦合。一个更好的主意是创建一个负责写入打印机 canvas 的接口(或类似的东西,你没有提供你的打印机代码所以这是一个猜测)并且打印机函数可以调用该方法传入的对象。打印机方法也应该只接受该接口作为参数。这是基于访问者模式。这是一个例子。
public interface IPrintable {
void WriteToPrinter(PrinterCanvas canvas);
}
public class Printer {
public void Print(IPrintable somethingToPrint) {
var canvas = getCanvas();
somethingToPrint.WriteToPrinter(canvas);
}
}
如果可能的话,您应该尽量避免像 Igor 在他的回答中所做的那样反思。
但如果您真的想使用反射,您目前检查的不是项目而是项目列表。
你应该尝试类似的东西(凭记忆写下):
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);
}
}
}
而不是 List<T>
创建一个接口,例如 ITicket 并接受 List<ITicket>
。每当您知道只能使用 Ticket 的东西时,使用 List<T>
作为泛型会产生不必要的广泛潜在输入。使用接口可以让你不用担心具体的实现,而只关注你的 dll 所关心的,即契约。
您可以将接口放在两个位置之一,或者是您的两个程序集都引用的另一个外部公共程序集,或者您可以将接口放在具有票证打印逻辑的程序集中。然后,您的 Ticket class 可以实现该接口。
示例:
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)
{
}
我有这段代码
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
}
}...
但我被困在那里。如何迭代列表中每个 属性 和每个原始 class 的值以便复制它?如果我创建一个断点,我可以看到字段和值已正确传递,但我不知道如何访问它们,所以我可以做一些事情,比如创建一个与原始列表完全一样的本地 class 并克隆列表(和如果我尝试它会说本地列表(Ticket)和传递的列表(T)不是同一类型)。
或者如果我在目标中创建一个精确的 class 并执行类似
的操作,我该如何复制它public void PrintTicketFromList(object lstArticles, short intCopies)
{
List<TargetDLLTicket> lst =((List<TargetDLLTicket>)lstArticles).ToList(); }
有什么想法吗?
听起来你遇到了循环依赖问题。您需要将发送到打印函数的类型移动到一个公共程序集(新项目),然后调用项目和打印项目都引用该程序集。然后两个项目都可以访问这个共享类型。
关于您的设计的注释。您处理此问题的方式可能一开始并不好,因此您的错误。实际的打印机函数不应该知道传入的类型的任何信息。一个好的经验法则是尝试使您的代码尽可能松散耦合。一个更好的主意是创建一个负责写入打印机 canvas 的接口(或类似的东西,你没有提供你的打印机代码所以这是一个猜测)并且打印机函数可以调用该方法传入的对象。打印机方法也应该只接受该接口作为参数。这是基于访问者模式。这是一个例子。
public interface IPrintable {
void WriteToPrinter(PrinterCanvas canvas);
}
public class Printer {
public void Print(IPrintable somethingToPrint) {
var canvas = getCanvas();
somethingToPrint.WriteToPrinter(canvas);
}
}
如果可能的话,您应该尽量避免像 Igor 在他的回答中所做的那样反思。
但如果您真的想使用反射,您目前检查的不是项目而是项目列表。
你应该尝试类似的东西(凭记忆写下):
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);
}
}
}
而不是 List<T>
创建一个接口,例如 ITicket 并接受 List<ITicket>
。每当您知道只能使用 Ticket 的东西时,使用 List<T>
作为泛型会产生不必要的广泛潜在输入。使用接口可以让你不用担心具体的实现,而只关注你的 dll 所关心的,即契约。
您可以将接口放在两个位置之一,或者是您的两个程序集都引用的另一个外部公共程序集,或者您可以将接口放在具有票证打印逻辑的程序集中。然后,您的 Ticket class 可以实现该接口。
示例:
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)
{
}