2015-05-29 70 views
2

我經常在linq嘗試建立一個對象並向它添加屬性時感到沮喪。在linq中建立一個對象 - 添加依賴於其他屬性的屬性

例子:

 var blgFiles = Directory.GetFiles(rootFolder, "*.blg", SearchOption.AllDirectories); 

    var data = blgFiles.Select(file => new 
    { 
     BLGFile = file, 
     CSVFile = Path.ChangeExtension(file, "csv"), 
     CSVFileExists = File.Exists(CSVFile) 
    }); 

這不能編譯,因爲我不能在File.Exists使用CSVFile。

我可能只是這樣做:

CSVFileExists = File.Exists(Path.ChangeExtension(file, "csv")) 

但這是多餘的。

我也可以做一個惱人的多種選擇,我手動複製的屬性,然後添加新的:

 var data = blgFiles.Select(file => new 
    { 
     BLGFile = file, 
     CSVFile = Path.ChangeExtension(file, "csv") 
    }); 

    var data2 = data.Select(file => new 
    { 
     BLGFile = file.BLGFile, 
     CSVFile = file.CSVFile, 
     CSVFileExists = File.Exists(file.CSVFile) 
    }); 

我只是想知道...還有什麼別的辦法嗎?我正在尋找可以快速添加屬性並創建對象的方法,其中一些屬性取決於以前屬性的值。

回答

2

你可以做的事情不多。另一種選擇:

var data = blgFiles.Select(file => 
{ 
    csvFile = Path.ChangeExtension(file, "csv"); 
    return new 
    { 
     BLGFile = file, 
     CSVFile = csvFile , 
     CSVFileExists = File.Exists(csvFile ) 
    } 
}); 

它仍然有額外的大括號的開銷,並且需要一個明確的return語句,這使得這個與簡化形式有點麻煩之間切換。 (除非你使用了Resharper,它爲你做。)

0

你可以「添加屬性和創建對象,其中一些屬性取決於先前屬性的值」,只需要有「先前」屬性。 對象初始化程序將所有屬性設置爲一個語句,這就是它的想法。

然而,您可以在select的lambda表達式中創建一個匿名方法,該方法返回所需的對象。在裏面,你可以編寫任意的C#代碼,這將允許你有多個語句,所以你會有「以前」的。

編輯:那示例代碼已被給出答案

0

這可能不是你的問題最好的例子,因爲你真的應該生成的文件的兩個列表,像加入他們:

var blgFiles = Directory.GetFiles(rootFolder, "*.blg", SearchOption.AllDirectories); 
var csvFiles = Directory.GetFiles(rootFolder, "*.csv", SearchOption.AllDirectories); 

var data = blgFiles.GroupJoin(csvFiles, 
    k=>Path.GetFilenameWithoutExtension(k), 
    v=>Path.GetFilenameWithoutExtension(v), 
    (k,g)=>g.Select(v=>new {BLGFILE=k,CSVFILE=v,CSVFileExists=true}) 
      .DefaultIfEmpty(new {BLGFILE=k,CSVFILE=Path.ChangeExtension(k,"csv"),CSVFile=false}) 
).SelectMany(g=>g); 

或者使用一個目錄查找:

var files=Directory.EnumerateFiles(rootFolder, "*.*", SearchOption.AllDirectories) 
     .Where(s => s.EndsWith(".blg") || s.EndsWith(".csv")); 

然後將它們分組,併產生最終輸出。這可能是最快的解決方案,因爲磁盤I/O相對昂貴,只做一次這部分可能會超過其他任何考慮因素。

當然,你總是可以做到這一點,但我懷疑你正試圖避免它:

var blgFiles = Directory.GetFiles(rootFolder, "*.blg", SearchOption.AllDirectories); 

var data = blgFiles.Select(file => new 
{ 
    BLGFile = file, 
    CSVFile = Path.ChangeExtension(file, "csv"), 
    CSVFileExists = File.Exists(Path.ChangeExtension(file, "csv")) 
}); 

但是,這會產生很多額外的磁盤的I/O,並調用ChangeExtension兩次。還有一個更簡單的版本,你也可以工作,但也有相同的缺陷:

var data = blgFiles.Select(file => new 
    { 
     BLGFile = file, 
     CSVFile = Path.ChangeExtension(file, "csv") 
    }).Select(file => new 
    { 
     BLGFile = file.BLGFile, 
     CSVFile = file.CSVFile, 
     CSVFileExists = File.Exists(file.CSVFile) 
    });