我正在遍历各种集合,如果满足特定的错误条件,那么我需要完整的对象图,即哪个索引有问题。
示例代码:
foreach (var sale in allSales) {
foreach (var discount in sale.orders.detail.discounts) {
if (errorConditionMet) {
// print full object graph. For example, perhaps it's the second Sale (index one), but first discount object (index zero):
// We have "discount" object, but want to print:
// allSales[1].sale.orders.detail.discounts[0]
}
可以只维护计数器(并且可能更高效):
string.Format("allSales[{0}].sale.orders.detail.discounts[{1}]", saleCount, discountCount);
// prints: allSales[1].sale.orders.detail.discounts[0]
但我想知道C#Reflection是否可以实现这一目标?我需要在多个类中使用它,所以将对象传递给方法并返回完全动态的对象图会很棒:
var resultOne = GetViaReflection(discount);
// returns: allSales[1].sale.orders.detail.discounts[0]
var resultTwo = GetViaReflection(currentAnimal);
// returns: animals[3].animal.types[2]
答案 0 :(得分:1)
使用常规for循环?
我不知道allSales
和sale.orders.detail.discounts
的类型,但我认为可以安全地假设它们至少是IEnumerable<T>
而List<T>
会从IEnumerable<T>
//If I wrap the IEnumerable in a list I get access to an indexer and count
var allSalesList = new List<T>(allSales);
for (int i = 0; i < allSalesList.Count; i++) {
var sale = allSales[i];
//If I wrap the IEnumerable in a list I get access to an indexer and count
var discounts = new List<T>(sale.orders.detail.discounts);
for (int j = 0; i < discounts.Count; j++) {
var discount = discounts[j];
if (errorConditionMet) {
// print full object graph. For example, perhaps it's the second Sale (index one), but first discount object (index zero):
// We have "discount" object, but want to print:
// allSales[1].sale.orders.detail.discounts[0]
//Your formatting here. I'm using C# 6 string interpolation, but its basically a string format.
Console.WriteLine($"allSales[{i}].sale.orders.detail.discounts[{j}]")
}
}
}
答案 1 :(得分:1)
考虑到这一点,但我认为这不可能以你的思维方式实现。
我有一段时间SO question similar to this正在寻找方法名称。保存的优点是我可以回到调用堆栈,但我不相信有任何类似于对象层次结构的调用堆栈。对象根本不知道有关引用它们的其他对象的任何信息。例如:
public class A {
public List<B> Objects { get; set; }
}
public class B {
public B(int i) { }
//blah
}
public static void Main(string[] args)
{
//Establish a simple object Heiarchy
//Root: A
/*
A
|-B1
|-B2
|-B3
*/
var alpha = new A()
{
Objects = new List<B>()
{
new B(1),
new B(2),
new B(3)
}
}
//MagicMethod<T>(object objectToTrace) is the mythical method that we're looking for
//What you're looking for is something like this:
MagicMethod(alpha.Objects[1]); //Should output "alpha.Objects[1]"
//But what if we make another reference to the same object?
var beta = alpha.Objects[1];
//Now what would MagicMethod() produce?
MagicMethod(beta); //would have to produce "beta"
//How is it possible that when We've called MagicMethod() with
//fundamentally the same argument, we get two different outputs?
}
正如您所看到的,我们的MagicMethod()
可能无法知道应该打印哪个参考。因此,即使如果一个对象在所有引用自身的地方都有记录,它也不可能选择正确的。
我希望我能够向你传达我的思路。我会在这里说:我不知道这是不是真的,但我无法想象这可能是真的。
答案 2 :(得分:-1)
如果我们抛开allSales
可以改变的明显问题并使索引暂时无效......
var salesWithErrors = allSales.Select((sale,saleIdx =>
new { Sale = sale, // not really needed for the particular example
Index = saleIdx,
DiscountsWithErrors = sale.orders.detail.discounts
.Select((d,i)=>new {
Discount = d,
Index = i,
})
.Where(di=>isErrorConditionMet(d.Discount))
})
.Where(saleDiscountErrors => saleDiscountErrors.DiscountsWithErrors.Any())
var results = string.Join(Environment.NewLine,
salesWithErrors.SelectMany(sde=>sde.DiscountsWithErrors.Select(d=>new{
SaleId = sde.Sale.Id,
SaleIndex = sde.Index,
DiscountId = d.Discount.Id
DiscountIndex = d.Index
})
.Select(sdi=>$"allSales[{sdi.SaleIndex}].sale.orders.detail.discounts[{sdi.DiscountIndex}]"));
您可以(应该)输出更持久的对象ID,而不是在短暂集合中输出索引,而是让您在数据库中找到它们,
...
.Select(sdi=>$"allSales[{sdi.SaleId}].sale.orders.detail.discounts[{sdi.DiscountId }]"