Table des matières
DotNet (.NET)
A étudier
WPF / XAML et la 3D dans les UI.
De la doc
developpez.com deviendrait-il une bonne référence …
Un super point d'entrée pour .NET :
http://www.csharpfriends.com/quickstart/howto/
Geaorge Shepherds's Windows Forms FAQ : Très complète sur les contrôles, le Framework et tout plein d'autres choses autour de .NET. Un must have !
Jon Skeet's C# and .NET articles and links: My book on C# 2 and 3, called C# in Depth, was recently published by Manning. Hopefully if you find these articles useful, you'll find the book handy too.
Classes et autres
BouncyCastle, CastleProject, iTextSharp, JayRock, NFOP, SharedCache, SharpZipLib, Spring.Net
www.mentalis.org : IniReader, Icmp, CpuUsage, StopWatch, Whois, DirectoryDialog, FileAssociation, MCI Controler, Crypto …
dotnet-project projets Dotnet Open Sources
PINVOKE.NET Sont référencées toutes les déclarations des APIs Windows.
Attempts to address the difficulty of calling Win32 or other unmanaged APIs in managed code (languages such as C# and VB .NET). Manually defining and using PInvoke signatures (also known as Declare statements in VB) is an error-prone process that can introduce extremely subtle bugs. The rules are complex, and if you make a mistake, you’ll probably corrupt memory.
SharpSSH: A Secure Shell (SSH) library for .NET.
SharpSSH is a pure .NET implementation of the SSH2 client protocol suite. It provides an API for communication with SSH servers and can be integrated into any .NET application.
The library is a C# port of the JSch project from JCraft Inc. and is released under BSD style license.
SharpSSH allows you to read/write data and transfer files over SSH channels using an API similar to JSch's API. In addition, it provides some additional wrapper classes which offer even simpler abstraction for SSH communication.
SharpPcap is a packet capture framework for the .NET environment, based on the famous WinPcap component. The purpose of this library is to provide an API for capturing, injecting, analyzing and building packets using any .NET language such as C# and VB.NET.
Web
NeatUpload
NeatUpload: The NeatUpload™ASP.NET component allows developers to stream uploaded files to storage (e.g. disk or a database) and allows users to monitor upload progress. It is open source and works under Mono's XSP / mod_mono as well as Microsoft's ASP.NET implementation.
NOTE: If your application does not have “Full” trust, a server administrator needs to install NeatUpload in the GAC, because needs to access the underlying HttpWorkerRequest object
Tips
Applications blocks
Array
Array.Contains
In the .NET Framework 2.0, System.Array implements the System.Collections.Generic.IList<T> interface. Unfortunately the implementation of the IList interface is provided at runtime so we do not see the methods in Visual Studio and we cannot write array.Contains(). Instead we have to cast the array to the appropriate IList interface:
string[] almostKilledToExtinction = new string[] { “Blue Whale”, “Snow Leopard”, “Giant Panda” }; if( ! ((IList<string>)almostKilledToExtinction).Contains(“Humans”) ) { System.Console.WriteLine(“phew!”); } System.Console.ReadLine();
Cette application est-elle déjà lancée ?
Créer un “Mutex nommé” au début de l'application avec un nom unique (le nom de l'appli + un GUID par exemple).
S'il est déjà créé au moment où on essai de le créer, c'est qu'une autre instance de l'appli tourne.
Question: et si l'appli plante, qui nettoie le Mutex ?
Réponse: Les objets du noyau sont libérés lorsque le process est terminé, pas de
problème de ce côté.
Ici un exemple : http://www.codeproject.com/csharp/SingleInstanceApplication.asp
Il y a aussi la méthode qui consiste à regarder les process en cours.
System.Diagnostics.Process[] proc = System.Diagnostics.Process.GetProcessesByName( System.Diagnostics.Process.GetCurrentProcess().ProcessName ); if (proc.Length > 1) { // le proccess a été trouvé }
opération dans le destructeur (~MaClasse)
Contrairement à C++, les destructeurs en C# ne sont pas déterministes; cela autant dans le temps que dans l'ordre. Sauf peut-être pour libérer des ressources externes à C# - tels que des handles de Windows - vous ne devriez jamais utiliser des ressources internes à C# dans un destructeur ou faire appel à d'autres objets référencés par un objet en cours de destruction.
Si vous voulez un ordre quelconque d'exécution une fois terminé l'usage d'un objet, vous devez créer une fonction (probablement virtuelle) et l'appeler avant de libérer celui-ci ou utiliser la méthode Dispose(true). Voir:
http://msdn.microsoft.com/msdnmag/issues/1100/GCI/default.aspx
http://msdn.microsoft.com/msdnmag/issues/1200/GCI2/default.aspx
http://www.martnet.com/~jfosler/articles/UsingDispose.htm
L'article de Jeff Richter est un peu vieux et certaines choses dedans ne sont plus bonnes car elles font référence à .NET 1.0 (il y a eu plusieurs changements au niveau du GC pour .NET 1.1) mais l'idée générale est là.
Debugger en mode Release
System.Diagnostics.Debugger.IsAttached
et mieux :
System.Diagnostics.Debugger.IsLogging()
Du coup:
public static bool isDebuggerActivated = System.Diagnostics.Debugger.IsLogging();
et ensuite:
if( isDebuggerActivated ) System.Diagnostics.Debugger.Log(0,“”,“Le message”+CRLF );
.NET Intéropérabilité code managé/non managé
Un bon aperçu ici : http://blogs.developpeur.org/neodante/articles/9744.aspx
l'article parle des DLLs, PInvoke et Marshaling puis un résumé sur le code non-managé.
Protection par l'obfuscation
Une présentation générale avec quelques produits :
http://www.supinfo-projects.com/fr/2004/application.net_to_logiciel/4/
Obtenir les liste des frameworks installés
Le petit outil .NET Version Detector X qui liste les frameworks installés.
Explication des clés de registre “officielles” concernant les frameworks .Net:
Reflection
public void setProperty(object oTargetObject, string strPropname, object oProperty) { System.Type myType = oTargetObject.GetType(); System.Reflection.PropertyInfo[] properties = myType.GetProperties(); foreach(System.Reflection.PropertyInfo pi in properties) { if( pi.CanWrite && pi.Name == strPropname ) { pi.SetValue(oTargetObject, oProperty, null); } } } public void callMethod(object oTargetObject, string methodName) { System.Type myType = oTargetObject.GetType(); MethodInfo mi = myType.GetMethod( methodName ); mi.Invoke( oTargetObject, new object[] {} ); }
MultiThreading
Articles:
- Multi-Threading en Java et .NET par Thomas GIL (Décembre 2003)
- Multi-threading in .NET donc un bon article sur le problem Deadlocks
- When to Run and When to Block 21 April 2009 by Andrew Hunter
Delegates et Evènements
Au coeur des delegates et des évènements .NET par Jean-Louis Vidal (Mai 2003).
Named Pipes
Inter-Process Communication in .NET Using Named Pipes.
at codeproject.com
Have you ever needed to exchange data between two .NET applications running on the same machine? For example a web site talking to a Windows service? The .NET Framework provides several good options for inter-process communication (IPC) like Web services and Remoting, the fastest being Remoting with a TCP channel and binary formatter.
The problem however is that Remoting is relatively slow, which most of the time is irrelevant, but if you need to make frequent “chatty” calls from one application to another and if your primary concern is performance, then Remoting might become an obstacle. What makes Remoting slow is not so much the communication protocol but the serialization.
Generally speaking Remoting is great but in the case when the IPC is confined to the local machine, it adds unnecessary overhead. That is why I started looking at alternatives, namely Named Pipes that will not involve binary serialization and will provide fast and lightweight IPC.
Events & Delegates
What's the difference between an event and a delegate?
Put simply, an event gives more limited access than a delegate. If an event is made public, code in other classes can only add or remove handlers for that event; they can't necessarily fire it, find out all the handlers for it, or remove handlers they don't know about. Events also allow more flexibility in terms of how the handlers are stored. For more details on this, see Eric Gunnerson's article on the topic.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp04192001.asp
.NET to Windows Internals
Windows HOOKs
MSDN's definition of a Windows hook is:
A hook is a point in the system message-handling mechanism where an application can install a subroutine to monitor the message traffic in the system and process certain types of messages before they reach the target window procedure.
Using Hooks from C#
http://www.codeproject.com/csharp/NetWin32Hooks.asp
Windows Hooks in the .NET Framework
http://msdn.microsoft.com/msdnmag/issues/02/10/CuttingEdge/
Windows Shell Integration
You need to write shell extension. This will be COM component.
Here are the docs on the subject :
http://msdn.microsoft.com/msdnmag/issues/04/01/WindowsShell/
http://www.kbcafe.com/juice/?guid=20041022155459
No you don't, for simple extensions like this you only really have to
add a few registry entries. It's described at
http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/programmersguide/shell_basics/shell_basics_extending/context.asp
And you shouldn't be writing shell extensions in managed code anyway.
Sur les performances
Il y a souvent plusieurs façon de faire la même chose, alors quelques tests de performances pour trancher.
Test sur le Type ou l'Héritage
Solution1: if(derivedInstance.GetType().IsSubclassOf(typeof(BaseType))) { }
Solution2: if(derivedType is BaseType) { }
Solution3: BaseType temp = derivedType as BaseType; if(temp != null) { }
- solution1 → took 949 ms for 1,000,000 iterations
- solution2 → took 3 ms for 1,000,000 iterations
- solution3 → took 2 ms for 1,000,000 iterations
Code Unsafe
Pour de nombreuses manips sur Grands tableaux ou sur de longues chaînes : Utiliser du Code Unsafe.
TODO: ajouter exemple manip image
Avec chaînes
Avec du code Unsafe :
public class Program { static unsafe void ToUpper(string str) { fixed (char* pfixed = str) for (char* p = pfixed; *p != 0; p++) *p = char.ToUpper(*p); } static void Main() { string str = "Bonjour"; System.Console.WriteLine(str); ToUpper(str); System.Console.WriteLine(str); } }
Performance ArrayList et Hashtable
Si l’on doit faire des recherches sur une liste, il vaut mieux utiliser une Hashtable plutôt qu’un ArrayList ! Différence entre des ajouts avec .Add() et des recherches avec arrayList.Contains() ou hashtable.ContainsKey()
Temps de traitement du même programme avec :
une Hashtable = 0,12 s un ArrayList = 2,8 s !!!
IHM, UI and other User Interface consideration
Keeping your UI Responsive and the Dangers of Application.DoEvents.
http://blogs.msdn.com/jfoscoding/archive/2005/08/06/448560.aspx
Windowing
The following sections describes the elements of an application with a Windows-based graphical user interface.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing.asp
Transparent controls
Making Transparent controls with C# :
http://www.c-sharpcorner.com/Code/2003/May/TransparentControls.asp
Customize MDI interface
Changer les propriétés du MDI Container, mettre un image en fond… Ca ne se fait pas aussi simplement que pour un Form. Ici se trouve la solution :
http://www.codeproject.com/cs/miscctrl/mdiclientcontroller.asp
Adding "Balloon" style to ToolTip
http://www.codeproject.com/cs/miscctrl/Balloon_ToolTip.asp
Need to call function SetBalloonStyle from place where the ToolTip window handle is created. In my example, I do it in OnLoad of the Form. If you call the function with handle which is not valid, exception will be thrown.
protected override void OnLoad(EventArgs e) { base.OnLoad (e); // set toolTip native window style to "balloon". NativeMethods.SetBalloonStyle ( toolTip1 ); }
Control RichTextbox
J'utilise un Richtextbox en bas d'un formulaire pour afficher les erreurs et autres messages. Pour que le Richtextbox scroll automatiquement vers le bas pour que l'on voit le dernier message, je n'ais pas trouvé d'autre moyen que d'envoyer un message windows.
using System.Runtime.InteropServices; [DllImport("user32.dll", EntryPoint="SendMessageA")] static extern uint SendMessage(System.IntPtr hwnd, uint wMsg, uint wParam, uint lParam); const int WM_VSCROLL = 0x115; const int SB_BOTTOM = 7; void printError(string msg) { ... // auto scroll SendMessage(this.report.Handle, WM_VSCROLL, SB_BOTTOM, 0); }
Updating your RichTextBox safely.
http://blogs.msdn.com/jfoscoding/archive/2005/05/26/422405.aspx
private delegate void RichTextBoxUpdateEventHandler(string message); private void UpdateRichTextBox(string message) { if (richTextBox1.InvokeRequired) { // this means we're on the wrong thread! // use BeginInvoke or Invoke to call back on the // correct thread. richTextBox1.Invoke( new RichTextBoxUpdateEventHandler(UpdateRichTextBox), // the method to call back on new object[] {message}); // the list of arguments to pass } else { richTextBox1.AppendText(message); } } private void nonThreadSafeTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { string messageToLog = "Timer ticked at: " + DateTime.Now.ToString() + "\r\n"; UpdateRichTextBox(messageToLog); }
Move a borderless window
C'est incroyable, mais ça fonctionne nickel. Pas besoin de s'embêter avec des conversion de coordonnées !
using System.Runtime.InteropServices; namespace WindowsFormsApplication1 { public partial class Form1 : Form { //const and dll functions for moving form public const int WM_NCLBUTTONDOWN = 0xA1; public const int HT_CAPTION = 0x2; [DllImportAttribute( "user32.dll" )] public static extern int SendMessage( IntPtr hWnd, int Msg, int wParam, int lParam ); [DllImportAttribute( "user32.dll" )] public static extern bool ReleaseCapture(); private void Form1_MouseDown( object sender, MouseEventArgs e ) { if( e.Button == MouseButtons.Left ) { ReleaseCapture(); SendMessage( Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0 ); } } private void button1_MouseDown( object sender, MouseEventArgs e ) { if( e.Button == MouseButtons.Left ) { ReleaseCapture(); SendMessage( Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0 ); } } } }
Data manipulation
HowTo, FAQ and Doc
Introducing ADO.NET and the Typed DataSet By Thom Robbins
101 Ways to Manipulate the DataGridView Control by Wei-Meng Lee (February 14, 2007)
Date & Time
Pour convertir un DateTime pour MySql
CultureInfo cult = new CultureInfo("sw-FI"); myDateTime.ToString("u", cult);
ou
DateTime myDateTime; INSERT INTO myTable SET StartTime = '" + myDateTime.ToString("yyyy:MM:dd hh:mm:ss") + "'";
et dans l'autre sens
MySqlDataReader reader ; DateTime modification = (DateTime) reader["Modification"] ;
Displaying Many-to-Many Relationships
Mapping Objet / Relationnel
MyGeneration - Code Generation, O/R Mapping, and Architectures
# Supported Architectures - dOOdads, Gentle.NET, Opf3, NHibernate, Microsoft's DAAB, EasyObjects/EntLib, DotNetNuke, iBatis
# Support for Twelve Different Database Systems.
Microsoft SQL, Oracle, IBM DB2, PostgreSQL, Microsoft Access, FireBird, Interbase, VistaDB, SQLite, MySQL, Advantage and Pervasive
# Template Based Code Generator Supporting Four Template Languages - JScript, VBScript, C# and VB.NET
http://www.mygenerationsoftware.com/portal/
Introduction progressive au Mapping Objet / Relationnel et mise en oeuvre avec une application console utilisant NHibernate.
http://kpixel.developpez.com/NHibernateEg/Tutorial1A/
NHibernate is a port of Hibernate Core for Java to the .NET Framework. It handles persisting plain .NET objects to and from an underlying relational database. Given an XML description of your entities and relationships, NHibernate automatically generates SQL for loading and storing the objects. Optionally, you can describe your mapping metadata with attributes in your source code.
NHibernate supports transparent persistence, your object classes don't have to follow a restrictive programming model. Persistent classes do not need to implement any interface or inherit from a special base class. This makes it possible to design the business logic using plain .NET (CLR) objects and object-oriented idiom.
Being a port of Hibernate 2.1, the NHibernate API is very similar to that of Hibernate. All Hibernate knowledge and existing Hibernate documentation is therefore directly applicable to NHibernate. Take a look at the list of Differences between Hibernate and NHibernate for a detailed comparison of Hibernate for Java and .NET.
The optional NHibernate Contrib package provides tools, additional mapping types, and cache providers.
XML
HowTo & FAQ
Sonu Kapoor maintains a dotNet's XML howto on his WebLog :
http://weblogs.asp.net/sonukapoor/articles/159790.aspx
Optimizing searches in readonly XML
XPathDocument & IndexingXPathNavigator are the solution.
The XPathDocument is faster than the XmlDocument in this respect, as it has been optimized for read-only operations (that can be cached).
The simplest solution is to load XML into XPathDocument (wghich is read-only, but takes in average 30% less memory), index it using IndexingXPathNavigator and query using key() function. Take a look at “XML Indexing Part 1: XML IDs, XSLT Keys and IndexingXPathNavigator” article at
http://msdn.microsoft.com/library/en-us/dnxmlnet/html/XMLindexing.asp
Yes, sure it works with .NET 1.1.
IndexingXPathNavigator is part of Mvp.Xml library now, just download appropriate Mvp.Xml lib version at
http://sourceforge.net/project/showfiles.php?group_id=102352
XML Serialization
tutoriel:
- La sérialisation XML avec .NET par Thomas Levesque (26/02/2009)
Custom XML Serialization
http://www.aspnetresources.com/blog/jumping_hoops_with_xml_serialization.aspx
http://weblogs.asp.net/cweyer/archive/2004/08/02/205798.aspx
Specials characters escaping
The character & needs to be escaped as & but any of the XML tools will do that automatically if you put it into a text node/content of an element or attribute e.g. the following C# code
string exampleURLWithQueryString = @"http://example.com/whoisgod?name=Kibo&domain=usenet"; XmlDocument xmlDocument = new XmlDocument(); xmlDocument.AppendChild(xmlDocument.CreateElement("example")); xmlDocument.DocumentElement.SetAttribute("link", exampleURLWithQueryString); xmlDocument.DocumentElement.AppendChild( xmlDocument.CreateTextNode(exampleURLWithQueryString) ); xmlDocument.Save(Console.Out);
will produce the markup
<example link="http://example.com/whoisgod?name=Kibo&domain=usenet"> http://example.com/whoisgod?name=Kibo&domain=usenet</example>
so all ampersands are properly escaped as &.
Same if you use an XmlTextWriter e.g. the C# code
string exampleURLWithQueryString = @"http://example.com/whoisgod?name=Kibo&domain=usenet"; XmlTextWriter xmlWriter = new XmlTextWriter(Console.Out); xmlWriter.WriteStartElement("example"); xmlWriter.WriteAttributeString("link", exampleURLWithQueryString); xmlWriter.WriteString(exampleURLWithQueryString); xmlWriter.WriteEndElement(); xmlWriter.Close();
gives the serialized markup
<example link="http://example.com/whoisgod?name=Kibo&domain=usenet"> http://example.com/whoisgod?name=Kibo&domain=usenet</example>
Thus if you use the proper tools to create your XML then there should not be a problem.
Remoting
Singleton object Server stop listening after a while
Problem:
Singleton server object which acts as the connection destination for
multiple client connections. After some period of time, server seems to quit listening, and client
connect attempts will time out. At this point, the only recovery is to restart the server process.
Solution:
Add this method :
public override object InitializeLifetimeService() { return null; }
Editors
SharpDevelop
MS Visual Studio .NET
Templates VS2003
Le template utilisé à la création d'une nouvelle classe est le fichier :
C:\Program Files\Microsoft Visual Studio .NET 2003\VC#\VC#Wizards\CSharpAddClassWiz\Templates\1036\NewCSharpFile.cs
Pour les Forms c'est :
C:\Program Files\Microsoft Visual Studio .NET 2003\VC#\VC#Wizards\CSharpAddWinFormWiz\Templates\1036\NewWinForm.cs
Add-In
Réalisation d'un Add-In :
http://www.dotnetguru.org/articles/outils/vsdotnet/dossieraddins/VSDotNetAddIn.htm
Tutorial sur les Plug-Ins Visual Studio :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsintro7/html/vxprodteproperty.asp