>

fredag 31 maj 2013

Trim funktionen ger inte samma resultat som tidigare

Microsoft ändrar tyvärr på vissa saker i nya versioner av frameworket, funktionerna Trim, TrimStart och TrimEnd är en sådan. I framework 3.5 SP1 och tidigare använde funktionerna en lista med vilka tecken som skulle tas bort medans i framework 4 och 4.5 används internt funktionen IsWhiteSpace från Char. Detta resulterar i att de senare versionen inte tar bort tecknen “zero width space” (200B) och “zero width no-break space” (FEFF). Båda är icke synliga men gör stor skillnad i en sträng jämförelse där alla tecken jämförs.

Lika så i framework 3.5 SP1 och tidigare fanns tre tecken som inte togs bort: “mongolian vowel separartor” (180E), “narrow no-break space” (202F) och “medium mathematical space” (205F).

Får du problem med detta i uppgraderad kod föreslår jag lösningen där du först kör trim följt av en borttagning av de två tidigare exkluderade tecknen:

myString.Trim().Trim(new[] { '\uFEFF', '\u200B' });

källa: http://msdn.microsoft.com/en-us/library/t97s7bs3.aspx

onsdag 8 maj 2013

Referenced assembly does not have a strong name

Vill du signera ditt program har du ett beroende på att alla referenser behöver vara signerade eller så kallade strong named. Visual Studio kommer att tala om vilka assemblys som inte är signerade genom ett meddelande i Error List: ’Referenced assembly x does not have a strong name’.
För dina egna assemblys är detta inget problem då du bara kan signera dem och kompilera om dem. För tredjeparts komponenter blir det lite svårare men det finns några kommandon du kan köra för att skapa nya signerade dll:er

Börja med att öppna ’Visual Studio Commando Promt’/’Developer Commando Promt’. Navigera sedan till platsen för dll filen (du måste inte men du slipper skriva hela sökvägen). Du behöver nu göra om filen till ett okompilerat format med hjälp av nedanstående kommando, förutsatt att filen heter filen.dll. Kommandot kommer att skapa flera filer, när du är klar med sista kommandot kan du ta bort alla dessa filer.
ildasm /all /output=filen.il filen.dll

Sedan behöver du en nyckel för själva signeringen, har du inte kan du skapa en med kommandot:
sn –k keyName.snk

Du avslutar med att skapa den signerade dll:en. Notera att nu används ilasm inte ildasm.
ilasm /dll filen.il /key=keyName.snk /output=filen.signed.dll

Du kan nu ta bort referensen till den gamla filen och lägga till den nya istället i ditt projekt.

måndag 6 maj 2013

Hitta dina Binding-fel

Alla som jobbar med WPF har många gånger skapat en binding som vid testkörning inte fungerar och sedan tillbringat en del tid med att gissa och testa olika varianter. När en binding är fel blir det nämligen inget exception fel som kastas som det blir med andra fel utan det bara sväljs av runtimen. Dock har felet fångats och ett meddelande har faktiskt skrivits. Om du tittar i Output fönstret nästa gång du får en binding som inte fungerar som den skall ser du att du har en text om vad som inte fungerar. Dock kommer det ut så mycket annat i detta fönster att det kan vara svårt att hitta just ditt fel. Önskvärt skulle ju vara att få detta på ett annat ställe eller ännu bättre få exception. Här har du två olika alternativ.

Få binding fel i en fil

I (System.Diagnostics.PresentationTraceSources) DataBindingSource.Listeners kollektionen kan du lägga in lyssnare som skall fånga upp databinding fel, redan nu ligger output-fönstret I denna kollektion. Men du kan också själv lägga till flera. TextWriterTraceListner är en av dem som du kan använda, då fångar du felen i en fil. I filen App.xaml.cs lägger du till följande funktion till klassen App.

static App()
{
  var bindingErrorLoggingFile = "din sökväg till en fil";
  System.Diagnostics.PresentationTraceSources.
   DataBindingSource.Listeners.Add(new
  TextWriterTraceListener(bindingErrorLoggingFile));
}

Få ett exception-fel

Om du istället vill få ett exception fel behöver du skriva en klass som går att lägga till listeners kollektionen och som när den får ett fel kastar exception. För att göra detta skapa en klass som ärver från TraceListner och som implementerar de funktioner som den basklassen kräver.

public class ExceptionTraceListner: TraceListener
{
  public override void Write(string message) {}
  public override void WriteLine(string message) {}
}

Sedan behövs en Exception klass som du kan kasta, visst duger någon av dem som finns men om du skriver en egen kan du utveckla den som du vill samt välja att fånga bara den i en try-catch.

public class BindingErrorException: Exception 
{
  public BindingErrorException(string message):base(message){}
}

Du kan nu välja att kasta detta exception när du fångar upp ett felmeddelande med din nya TraceListner (ExceptionTraceListner klassen). Jag rekommenderar även att lägga in ett DEBUG direktiv så att du inte får med detta beteende ut i produktion.

public override void WriteLine(string message)
{
#if DEBUG
  throw new BindingErrorException(message);
#endif
}

Du behöver nu bara lägga till lyssnaren till DataBindingSources Listners kollektion. I filen App.xaml.cs (App.xaml.vb) lägg till följande funktion till klassen App

static App()
{
  System.Diagnostics.PresentationTraceSources.
    DataBindingSource.Listeners.Add(new ExceptionTraceListner());
}