Assumere questa catena di riferimenti dllPerché chiamare IEnumerable <string> .Count() crea una dipendenza aggiuntiva dall'assembly?
Tests.dll >> Automation.dll >> White.Core.dll
con la seguente riga di codice nella Tests.dll, dove tutto si basa
result.MissingPaths
Ora quando cambio a questo
result.MissingPaths.Count()
I ottenere il seguente errore di generazione per Tests.dll "White.UIItem non è definito in un assembly a cui non viene fatto riferimento. È necessario aggiungere un riferimento a White.Core.dll." E non voglio farlo perché rompe la mia stratificazione.
Ecco la definizione del tipo di risultato, che è in Automation.dll
public class HasResult
{
public HasResult(IEnumerable<string> missingPaths)
{ MissingPaths = missingPaths; }
public IEnumerable<string> MissingPaths { get; set; }
public bool AllExist
{
get { return !MissingPaths.Any(); }
}
}
giù la catena chiamata viene creato il parametro di ingresso a questa ctor via (La classe TreeNode è in White.Core.dll)
assetPaths.Where(assetPath => !FindTreeNodeUsingCache(treeHandle, assetPath));
Perché questa perdita di dipendenza quando si chiama Count() su IEnumerable? Ho quindi sospettato che questa valutazione pigra causasse questo (per qualche ragione), quindi ho inserito un ToArray() nella riga sopra ma non ha funzionato.
Aggiornamento 2011 01 07: Curioso e curioso! non verrà creato finché non aggiungo un riferimento a White.Core. Quindi aggiungo un riferimento e lo costruisco (per trovare l'elusiva fonte di dipendenza). Aprilo in Reflector e gli unici riferimenti elencati sono Automation, mscorlib, System.core e NUnit. Quindi il compilatore ha gettato via il riferimento Bianco in quanto non era necessario. ILDASM conferma anche che non esiste una voce White AssemblyRef.
Qualche idea su come arrivare alla fine di questa cosa (principalmente per le ragioni "ora voglio sapere perché")? Quali sono le probabilità che si tratti di un bug VS2010/MSBuild?
Aggiornamento 2011 01 07 # 2 Come da suggerimento di Shimmy, provato a chiamare il metodo explcitly come un metodo di estensione
Enumerable.Count(result.MissingPaths)
e si ferma cribbing (non so perché).
Tuttavia ho spostato un po 'di codice in seguito e ora sto ricevendo lo stesso problema in una posizione diversa utilizzando IEnumerable - questa volta la lettura e il filtraggio di righe su un file su disco (totalmente estraneo al Bianco). Sembra che sia una "correzione dei sintomi".
var lines = File.ReadLines(aFilePath).ToArray();
ancora una volta, se rimuovo il ToArray() viene compilato di nuovo - sembra che qualsiasi metodo che fa valutare l'enumerabile (ToArray, Count, ToList, ecc.) Lo fa. Mi permetta di cercare di ottenere un lavoro piccolo-app di demo questo problema ...
Aggiornamento 2011 01 07 # 3 Accidenti! Ulteriori informazioni .. Si scopre che il problema è solo in un file sorgente: questo file è LINQ-phobic. Qualsiasi chiamata a un metodo di estensione enumerabile deve essere esplicitamente richiamata. I refactoring che ho fatto hanno causato il trasferimento di un nuovo metodo in questo file sorgente, che aveva alcuni LINQ :) Ancora nessun indizio sul motivo per cui questa classe non piaccia LINQ.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using G.S.OurAutomation.Constants;
using G.S.OurAutomation.Framework;
using NUnit.Framework;
namespace G.S.AcceptanceTests
{
public abstract class ConfigureThingBase : OurTestFixture
{
....
private static IEnumerable<string> GetExpectedThingsFor(string param)
{
// even this won't compile - although it compiles fine in an adjoining source file in the same assembly
//IEnumerable<string> s = new string[0];
//Console.WriteLine(s.Count());
// this is the line that is now causing a build failure
// var expectedInfo = File.ReadLines(someCsvFilePath))
// .Where(line => !line.StartsWith("REM", StringComparison.InvariantCultureIgnoreCase))
// .Select(line => line.Replace("%PLACEHOLDER%", param))
// .ToArray();
// Unrolling the LINQ above removes the build error
var expectedInfo =
Enumerable.ToArray(
Enumerable.Select(
Enumerable.Where(
File.ReadLines(someCsvFilePath)),
line => !line.StartsWith("REM", StringComparison.InvariantCultureIgnoreCase)),
line => line.Replace("%PLACEHOLDER%", param)));
Aggiornamento 2011 01 11 # 4 ristretto la scelta a quello che sembra il colpevole, ma nessun movente :)
ripresa la quest post il fine settimana .. e utilizzando il processo evergreen di eliminazione, è stato in grado di entra nel bit offendente. Il problema è la seguente direttiva using nel file di origine in Tests.dll
using G.S.OurAutomation.Framework;
dopo sono andato dopo il sospetto più probabile all'interno di questo spazio dei nomi e ho avuto WhiteExtensions sotto i riflettori.
namespace G.S.OurAutomation.Framework
{
public static class WhiteExtensions
{
public static T PollAndGet<T>(this Window parentWindow, string automationId) where T : UIItem ...
public static Window WaitForWindowWithTitle(this Application application, string windowTitle) ...
public static bool HasTreeNode(this Tree treeHandle, string assetPath) ...
public static HasTreeNodesResult HasTreeNodes(this Tree treeHandle, IEnumerable<string> assetPaths)...
}
}
Questo ha portato a 3 correzioni, che funzionano entrambe.
- Trasforma i metodi di estensione in normali metodi statici.
- Spostare questa classe in un subnamespace
G.S.OurAutomation.Framework.White
- rendere questo una classe interna (in quanto è destinato per il consumo interno .. ancora una volta la linea guida di scegliere il modificatore di accesso più restrittivo mi morde.)
Anche se la mia istanza specifica è corretta, questo aggiornamento può aiutare qualcuno a spiegarne il motivo? Se non shimmy ottiene il segno di spunta :) per indicare verso la giusta direzione.
potresti fornire altro codice? E forse rinominare le DLL in qualcosa di più significativo? Forse W.Type non è referenziato dove viene dichiarato un metodo di estensione? – James
Prova ad aggiungere W.dll come riferimento al progetto T. – Steven
@James - Assegnato agli assembly :) Quello che sta facendo il codice (in breve) è: Verificare se alcuni nodi esistono in una struttura mostrata sulla GUI? risultato è un tipo che include un valore di successo booleano + un elenco di nodi mancanti, se presenti. Quindi Tests.dll utilizza Automation.dll - Driver.HasNodes() per fare la sua cosa, tuttavia l'impl. il dettaglio che Automation.dll utilizza per eseguire il lavoro non dovrebbe strisciare fuori dal livello di automazione. Il codice prevede la restituzione di un oggetto IEnumerable (percorsi completi Root \ parent \ child) dal livello interno al client per la segnalazione degli errori. –
Gishu