SWL004
VS.NET and C#Tips and Tricks
Juval Löwy
www.idesign.net
About Juval LöwySoftware architect
Consults and trains on .NET migration and design
MS Regional Director for the Silicon Valley
AuthoredProgramming .NET components (2003, O’Reilly)
COM and .NET component services (2001, O’Reilly)
Participates in the .NET design reviews
Contributing editor and columnist to the Visual Studio Magazine
Contact at www.idesign.net
WinCV
Header-file-like type information"C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin\WinCV.exe"
WinCV
.NET Best-kept secret
Intelisense on steroidsBase types
Other methods
Quick referenceSaves sifting through MSDN
Can customize assembly listWinCV.exe.config
Large project life saver
Linked FilesLinked mode for opening a file
References the file for compilation purpose, but does not copy it
Example: SolutionInfo.cs file, sharing:snk file
Version
Security policy
Copyrights
Company name
Multiple Projects StartupCan launch multiple applications from the same solution
Same debug session with F5 (Start button )
Solution|Properties|Startup Project
Blank Solution
Often, solution contains multiple projects
Solution file should not be part of any specific project
The result of adding projects to existing project
Create a blank solutionFile|New|Blank solution…
Add projects to it
Can also use Empty Project as template for content and structure
Task List
Machine-generated entriesCompilation errors
Click to source
//TODO in the code adds a task
Build EventsAdd pre/post build action
C# .NET 1.1 only
Example- Registering in the GAC after successful build
Build Events
Can use marcos
Treat Warnings as Errors Project Properties|Configuration Properties|Build
Make sure level 4 warning level is set
A must for release buildPreferable debug as well
Drag-and-Drop Elements
Windows Form, Web Form, Web Services can accept drag-n-drop
SQL tableGenerates adaptor, connection, command, dataset
Components Event log, directory watcher, timer, etc
Drag-and-Drop Elements
To add ability to mere classes, derive from Component
System.ComponentModel
Can remove derivation later on
VS.NET displays component icon
using System.ComponentModel;
namespace MyClassLibrary
{
public class MyClass : Component
{…}
}
Rectangular Selection
Press ALT while dragging cursor to mark section
Very useful in removing namespaces and repeated definitions
Document Outline
Hierarchy navigation ASP.NET forms, HTML, XML
Helpful in complex files View|Other Windows|Document Outline
C# Event AccessorsInstead of raw event member, use add/remove accessors
Like properties
Promote encapsulation and loose couplingpublic delegate void MyDelegate(int num); public class MySource{ protected event MyDelegate m_NumberChangedEvent; public event MyDelegate NumberChangedEvent { add { m_NumberChangedEvent += value; } remove { m_NumberChangedEvent -= value; } }}
C# Event Accessors
Subscriber uses “normal” event syntax:
public class MySink{ public void OnNumberChanged(int num) { MessageBox.Show(num.ToString()); }}
MySource source = new MySource();MySink sink = new MySink();
source.NumberChangedEvent += new MyDelegate(sink.OnNumberChanged);
Context-Bound ObjectApp domains are subdivided into contexts
Process A
AppDomain A
Context 1
Context 2
Process B
AppDomain B
Context 3
Context 4
AppDomain C
Context 5
Executes in exactly one contextFixed for life
Any class derived from ContextBoundObject
Context bound is also marshaled by ref
ContextBoundObject derives from
MarshalByRefObject
All calls intercepted
Context-Bound Object
public class MyClass : ContextBoundObject{…}
Example - Synchronization
.NET associates object with a shared lock
.NET intercepts calls coming into the contextTries to acquire lock (blocks if owned by another thread)
Unlocks lock on the way out of context
Pending callers queued
using System.Runtime.Remoting.Contexts;
[Synchronization]public class MyClass : ContextBoundObject{ public MyClass(){} public void DoSomething(){} //other methods and data members }
Interception Architecture
Context-bound object always accessed via proxy
App Domain
Context 1
Client
Context 2
Proxy(interception)
ContextBoundObject
Interception Architecture
TransparentProxy
Client
MethodCall()
RealProxy
ContextBoundObject
Message Sink A
Sink B Message
Sink B
StackBuilder
SinkMessage
MethodCall()
The Logbook Service
MotivationMethod call tracing and error logging are crucial to robust and faster development time
In distributed environment flight recorder is worth its weight in gold
By examining log entries, you analyze what took place, across machines and applications, and the source of the problem is almost immediately evident
Useful in post deployment, to troubleshoot customer problems
The Logbook Service
What is loggedLocation: machine, app domain name, thread (ID and name), context ID
Caller’s identity (user name)
Target object : assembly, type, member being accesses
Date and time
Exception type and message
The Logbook Service
Using the logbook
Can specify filter:
using ContextLogger; [Logbook]public class MyClass : ContextBoundObject{…}
public enum LogOption{ MethodCalls,//Default Errors} [Logbook(LogOption.Errors)]public class MyClass : ContextBoundObject{…}
The Logbook Architecture
Proxyand
InterceptionClient
[Logbook]
ContextBoundObject
LogSink
Database
LogbookSingleton
Logbook Viewer
Loosely Coupled Events
Effective way of de-coupling components
Other capabilities such as security, queuing, transactions
With delegate-based events:Client has to subscribe per event per publisher
Coupled life line
Cannot subscribe to type
No administrative setting of connection
LCE lets you configure subscriptions
LCE has separate life line
Can subscribe existing objects as well
Loosely Coupled Events
Deliver the event to .NET, not the subscribers
PersistentSubscriber
ISink
Component(publisher)
.NETEnterpriseServices
Component persistent subscription list
TransientSubscriber
ISink
Register Transient Subscription
Fire eventFires event
2
Please Publish3
Create
5
Fire event6
7
Look for a subscription4
ISink
Create1
Event Class
Loosely Coupled Events
EventClassAttribute denotes a managed class as an event class
public interface IMySink{ void OnEvent1(); void OnEvent2();}
[EventClass]public class MyEventClass : ServicedComponent,IMySink{ public void OnEvent1() {} public void OnEvent2() {}}
Publishing event
Can fire in parallel
IMySink sink;sink = new MyEventClass();sink.OnEvent1();
[EventClass(FireInParallel = true)]public class MyEventClass : ServicedComponent{ public void OnEvent1() {} public void OnEvent2() {}}
Loosely Coupled Events
Loosely Coupled Events
Persistent subscribersGet created to handle event
Admin support
Persist machine reboot
Transient subscribersNotifying existing subscribers
Gone after machine reboot
No out-of-the-box supportUse my helper class
No admin support
Conditional Compilation
Exclude method call from compilationWhen the condition is not defined
System.Diagnostics
#define MySpecialCondition //usually DEBUGpublic class MyClass{ public MyClass() {} [Conditional("MySpecialCondition")] public void MyMethod() {}}//Client side codeMyClass obj = new MyClass();//This line is conditionalobj.MyMethod();
Killing a Thread
Do not call Abort()Thread may need to do clean-up
Abort() does not allow graceful exit
Abort() is not guaranteed to workThread can do indefinite processing in catch{}
ResetAbort(), suspended, interop calls
The thread method should check a flagProtect flag with a lock
Kill() method should set flag and wait for thread to terminate
public class WorkerThread : IDisposable{ protected Thread m_ThreadObj; protected bool m_EndLoop; protected Mutex m_EndLoopMutex; protected bool EndLoop { set { m_EndLoopMutex.WaitOne(); m_EndLoop = value; m_EndLoopMutex.ReleaseMutex(); } get { bool result = false; m_EndLoopMutex.WaitOne(); result = m_EndLoop; m_EndLoopMutex.ReleaseMutex(); return result; } } public WorkerThread() { m_EndLoop = false; m_ThreadObj = null; m_EndLoopMutex = new Mutex(); }
public class WorkerThread : IDisposable{ public void Start() { m_ThreadObj = Thread.CurrentThread; int i = 0; while(EndLoop == false) { //do work here } }
//Kill is called on client thread - must use cached thread object public void Kill() { Debug.Assert(m_ThreadObj != null); if(m_ThreadObj.IsAlive == false) return; EndLoop = true; //Wait for thread to die m_ThreadObj.Join();
if(m_EndLoopMutex != null) m_EndLoopMutex.Close(); } //Rest of WorkerThread
Thread HandleThread Handle
ThreadThread does not provide a does not provide a WaitHandleWaitHandleUnlike Windows Unlike Windows
Join()Join() is not good enough is not good enough Cannot combine in multiple wait operationCannot combine in multiple wait operation
No atomic wait No atomic wait
Have the wrapper class expose a event Have the wrapper class expose a event handle handle
Signaled when the thread method exists Signaled when the thread method exists In In finallyfinally statement statement
public class WorkerThread { protected ManualResetEvent m_ThreadHandle; public WorkerThread() { m_ThreadHandle = new ManualResetEvent(false); //More initialization } public WaitHandle Handle { get { return m_ThreadHandle; } } private void Run() { try { //Do work here } finally { m_ThreadHandle.Set(); } } //Rest of the implementation }
More at TechEd
C# Best Practices DEV312
Distributed Security PracticesDEV354
Building High-Performance Applications with Visual Studio .NET
DEV326
Application and Library VersioningDEV343
Software Legends – VS.NET and C# tips and tricksSWL004
ResourcesResourcesProgramming .NET components
By Juval Lowy, O'Reilly April 2003
www.idesign.net
.NET Master Class3-4 annually
Upcoming events onwww.idesign.net
Community Resources
Community Resourceshttp://www.microsoft.com/communities/default.mspx
Most Valuable Professional (MVP)http://www.mvp.support.microsoft.com/
NewsgroupsConverse online with Microsoft Newsgroups, including Worldwidehttp://www.microsoft.com/communities/newsgroups/default.mspx
User GroupsMeet and learn with your peershttp://www.microsoft.com/communities/usergroups/default.mspx
SOFTWARE LEGENDSOFTWARE LEGENDJuval LowyJuval Lowy
THURSDAY 3rd JULY at 16.15-16.45 hrs
Meet the Author’sMeet the Author’s Book signingBook signing
evaluationsevaluations
© 2003 Microsoft Corporation. All rights reserved.© 2003 Microsoft Corporation. All rights reserved.This presentation is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.This presentation is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.