odern applications are no longer isolated, stand-alone applications, limited to a single process or machine. Distributed applications allow you to put components in close proximity to the resources they use, allow multiple users to access the application, enable scalability and throughput, and increase overall availability and fault isolation. Component-oriented programming is especially geared towards distribution because it is all about breaking the application into a set of interacting components, which you can then distribute to different locations. .NET has a vast infrastructure supporting distributed applications and remote calls. This article focuses on just a single aspect of .NET remoting: the different object activation models available to a distributed application.
Understanding the remote object activation models is key to successfully applying .NET in a distributed environment. .NET offers multiple activation models because modern applications often need to cater to drastically different scalability, throughput and performance requirements, and there is no one-size-fits-all solution. Consequently, choosing the right activation model is actually the single most critical design decision you will have to make when designing and building a distributed application in .NET. .NET remoting has a lot more to it than just the activation model, but in many respects these are mere programming details. Most of these details make no sense unless you understand the activation models, you know how to chose one, and you learn how to implement the matching components. I will cover other facets of .NET remoting in future articles. My emphasis in this article is on understanding the basic concepts, the tradeoffs they offer, and the practical aspects of the different activation models.
App Domains and Remote Objects Types
.NET applications run inside an unmanaged Windows process. However, .NET applications require a managed code environment. To bridge this gap, .NET introduces the app domaina logical managed process inside a raw, physical process. App domains provide assemblies they load and the components inside them many of the same services an unmanaged process provides unmanaged objects and libraries. A single physical process can contain multiple app domains, although typically only large application frameworks require it. Every process starts with a single app domain. If the object is in the same app domain as the client then usually no proxies are involved and the client holds a direct reference to the object. The question is what happens when you try to call methods on a remote object in another app domain? By default, objects are not accessible from outside their app domain, even if the call is made between two app domains in the same process. The rationale behind this decision is that .NET must first enforce app domain isolation and security.
If you want your objects to be accessed from outside their app domain, then you must allow it explicitly in your design and class definition. .NET provides two options for accessing an object across an app domain boundary: by value or by reference. By value means the object is first copied across the app domain boundary, so that the remote client gets its own cloned copy of the original object. Once a copy is transferred to the remote client, the two objects are distinct and can change state independently. This is similar to COM marshal by value, and it is often referred to as marshaling by value. The second way of accessing a remote object is by reference, meaning that the remote clients only hold a reference to the object in the form of a proxy. Access by reference is often referred to as marshaling by reference. (See Sidebar: Short Circuiting Remoting)