Proxies

I'm sure that everyone's reaction to the contract concept is that it is very strict, that it can get complicated quickly, and that it is important to get it right and keep it right. In other words, you don't want just anyone partying in the contract space. Furthermore, the programming model presented by contracts is not very .NET friendly. For these reasons we have in the MAF model an abstraction that lives on top of the contracts called a "proxy."

Of course, proxy is one of those computer terms that has dozens of particular meanings. The general meaning of a "proxy" is "the authority to act for another." Computer proxies adhere to this meaning, and ours is no different. But the MAF proxy doesn't act on behalf of the contract, it acts through the contract on behalf of the underlying implementation. (We'll cover what the underlying implementation looks like in the next article: Adapters). The proxy presents a .NET Friendly programming model that represents or proxies the "real" implementation in the host application. As such, in many cases, its public surface probably looks suspiciously similar to that real class's public surface. The difference is that the implementation of the proxy is simply to call through a contract or contracts.

If you are familiar with .NET Remoting, you know that they have proxies too. In fact, these are used internally in MAF, as it is built on top of .NET Remoting. When a MAF proxy calls into a contract, assuming it is crossing a remoting boundary, it is really calling into a .NET Remoting Transparent Proxy for that contract. And that transparent proxy is backed, in .NET, by a "Real Proxy" that translates method calls on the Transparent Proxy into messages sent through the remoting channel. To differentiate the MAF Proxy from .NET Remoting's transparent proxy, I sometimes refer to the MAF Proxy as an "Opaque Proxy."

If MAF is using proxies already, internally, why do we need this extra layer of abstraction? The reason is in the Transparent Proxy itself. The Transparent Proxy is created in the remote appdomain with a particular System.Type instance that tells it what to emulate. If this System.Type is *not* a contract, then we are leaking types from the host. So while Transparent Proxy is not an instance of the type it is proxying for, it still *requires* an instance of that class's System.Type; in short it requires that the type be loaded into both AppDomains. As we know from from the discussions on Contracts, only Contract Types are allowed to span the boundaries.

So Opaque Proxies are their own types, isolated from the "real" types by contracts. They just happen to look like the real types. Transparent Proxies emulate the real instance by grabbing hold of its actaul System.Type. Opaque proxies, then, provide a level of abstraction on top of Transparent Proxies to keep us from leaking host types. The only Transparent Proxies in MAF are for contract types.

One must, then, create a Opaque Proxy class for each type one wishes to proxy and implement it to call through a contract. This can get daunting (and tedious) quickly. Fortunately, we are working on a tool -- proxygen -- that generates proxies given an existing assembly as input. This will be in the upcoming VSTA SDK.

Next, I will go into more detail on what contract implementations look like.