2015-12-02 44 views
1

我通過各種藏品循環,如果特定錯誤條件滿足,那麼我需要完整的對象圖,即指數有問題。獲取完整的對象圖形字符串C#

示例代碼:

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#反射?我需要在這多個類,所以這將是偉大的一個對象傳遞給方法,並返回對象圖,完全動態:

var resultOne = GetViaReflection(discount); 
// returns: allSales[1].sale.orders.detail.discounts[0] 
var resultTwo = GetViaReflection(currentAnimal); 
// returns: animals[3].animal.types[2] 
+3

'foreach'隱藏一個枚舉,而[_「一個指數的概念是陌生的枚舉的概念」 _(HTTP: //stackoverflow.com/questions/43021/how-do-you-get-the-index-當前迭代的一個foreach循環),所以我猜你沒有運氣。 – CodeCaster

+0

對象沒有索引...(或者它們存儲在其中的父項或數組,IEnumerable沒有搜索的概念)。所以不太清楚你希望如何使用反射來找到不存在的東西。 –

+0

'allSales'和'sale.orders.detail.discounts'有什麼類型? –

回答

1

使用普通的循環? 我不知道類型的allSalessale.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}]") 
     } 
    } 
} 
+0

是的,所有IEnumerable 。看到我的問題編輯,我進一步澄清,這將是重用的目標。謝謝! – dotNetkow

+1

我剛剛看到提交後,我!呃,好吧。我認爲這會回答你原來的問題,但這種(涉及反思)的一般情況可能會出現在別人的答案中。 –

+0

你的答案是最簡單的方法。我受到了FluentValidation庫的啓發,它想要重新創建它。結果表明它建立了一個「財產鏈」,隨着它向下而建立。本質上:有些反思,但沒有魔力子彈。 – dotNetkow

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()着可能知道哪些引用應該打印。因此,即使如果一個對象有一個關於所有引用自身的地方的記錄,它不可能選擇正確的一個。

我希望我能夠轉達我想給你的線。我會在這裏說:我不知道這是否屬實,但我無法想象一種可能是真實的方式。

-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 }]" 
相關問題