Sunday, April 13, 2008

Miscellaneous

How does .NET remoting work?

.NET remoting involves sending messages along channels. Two of the standard channels are HTTP and TCP. TCP is intended for LANs only - HTTP can be used for LANs or WANs (internet).

Support is provided for multiple message serializarion formats. Examples are SOAP (XML-based) and binary. By default, the HTTP channel uses SOAP (via the .NET runtime Serialization SOAP Formatter), and the TCP channel uses binary (via the .NET runtime Serialization Binary Formatter). But either channel can use either serialization format.

There are a number of styles of remote access:

  • SingleCall. Each incoming request from a client is serviced by a new object. The object is thrown away when the request has finished.
  • Singleton. All incoming requests from clients are processed by a single server object.
  • Client-activated object. This is the old stateful (D)COM model whereby the client receives a reference to the remote object and holds that reference (thus keeping the remote object alive) until it is finished with it.

Distributed garbage collection of objects is managed by a system called 'leased based lifetime'. Each object has a lease time, and when that time expires the object is disconnected from the .NET runtime remoting infrastructure. Objects have a default renew time - the lease is renewed when a successful call is made from the client to the object. The client can also explicitly renew the lease.

If you're interested in using XML-RPC as an alternative to SOAP, take a look at Charles Cook's XML-RPC.Net.

How can I get at the Win32 API from a .NET program?

Use P/Invoke. This uses similar technology to COM Interop, but is used to access static DLL entry points instead of COM objects. Here is an example of C# calling the Win32 MessageBox function:

    using System; 
using System.Runtime.InteropServices;

class MainApp
{
[DllImport("user32.dll", EntryPoint="MessageBox", SetLastError=true, CharSet=CharSet.Auto)]
public static extern int MessageBox(int hWnd, String strMessage, String strCaption, uint uiType);

public static void Main()
{
MessageBox( 0, "Hello, this is PInvoke in operation!", ".NET", 0 );
}
}

Pinvoke.net is a great resource for off-the-shelf P/Invoke signatures.

How do I write to the application configuration file at runtime?

You don't. See http://www.interact-sw.co.uk/iangblog/2004/11/25/savingconfig.

What is the difference between an event and a delegate?

An event is just a wrapper for a multicast delegate. Adding a public event to a class is almost the same as adding a public multicast delegate field. In both cases, subscriber objects can register for notifications, and in both cases the publisher object can send notifications to the subscribers. However, a public multicast delegate has the undesirable property that external objects can invoke the delegate, something we'd normally want to restrict to the publisher. Hence events - an event adds public methods to the containing class to add and remove receivers, but does not make the invocation mechanism public.

See this post by Julien Couvreur for more discussion.

What size is a .NET object?

Each instance of a reference type has two fields maintained by the runtime - a method table pointer and a sync block. These are 4 bytes each on a 32-bit system, making a total of 8 bytes per object overhead. Obviously the instance data for the type must be added to this to get the overall size of the object. So, for example, instances of the following class are 12 bytes each:

    class MyInt
{
...
private int x;
}

However, note that with the current implementation of the CLR there seems to be a minimum object size of 12 bytes, even for classes with no data (e.g. System.Object).

Values types have no equivalent overhead.

Will my .NET app run on 64-bit Windows?

64-bit (x64) versions of Windows support both 32-bit and 64-bit processes, and corresponding 32-bit and 64-bit versions of .NET 2.0. (.NET 1.1 is 32-bit only).

.NET 1.x apps automatically run as 32-bit processes on 64-bit Windows.

.NET 2.0 apps can either run as 32-bit processes or as 64-bit processes. The OS decides which to use based on the PE header of the executable. The flags in the PE header are controlled via the compiler /platform switch, which allows the target of the app to be specified as 'x86', 'x64' or 'any cpu'. Normally you specify 'any cpu', and your app will run as 32-bit on 32-bit Windows and 64-bit on 64-bit Windows. However if you have some 32-bit native code in your app (loaded via COM interop, for example), you will need to specify 'x86', which will force 64-bit Windows to load your app in a 32-bit process. You can also tweak the 32-bit flag in the PE header using the SDK corflags utility.

Some more explanation here:

http://blogs.msdn.com/gauravseth/archive/2006/03/07/545104.aspx
http://blogs.msdn.com/joshwil/archive/2005/04/08/406567.aspx
http://msdn.microsoft.com/netframework/programming/64bit/gettingstarted/

What is reflection?

All .NET compilers produce metadata about the types defined in the modules they produce. This metadata is packaged along with the module (modules in turn are packaged together in assemblies), and can be accessed by a mechanism called reflection. The System.Reflection namespace contains classes that can be used to interrogate the types for a module/assembly.

Using reflection to access .NET metadata is very similar to using ITypeLib/ITypeInfo to access type library data in COM, and it is used for similar purposes - e.g. determining data type sizes for marshaling data across context/process/machine boundaries.

Reflection can also be used to dynamically invoke methods (see System.Type.InvokeMember), or even create types dynamically at run-time (see System.Reflection.Emit.TypeBuilder).

No comments: