Click here to Skip to main content
11,413,548 members (68,545 online)
Click here to Skip to main content
Add your own
alternative version

.NET Remoting and Cross Domain Marshalling

, 10 Apr 2006 CPOL
An article about how to marshal a remote client request from one AppDomain to another.
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Permissions;
using System.Reflection;

using System.Runtime.Remoting;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Channels;


namespace ContextBoundRemoting
{
    /// <summary>
    /// 
    /// </summary>
    [CrossDomainContext]
    class CrossDomainMarshaller : ContextBoundObject
    {
        public static Dictionary<string, ICrossDomainService> Dictionary = new Dictionary<string, ICrossDomainService>();

        public static ICrossDomainService GetService(string clientID)
        {
            if (Dictionary.ContainsKey(clientID))
                return Dictionary[clientID];

            AppDomain appDomain = AppDomain.CreateDomain(clientID);
            ICrossDomainService service = (ICrossDomainService)appDomain.CreateInstanceAndUnwrap(
                "ContextBoundRemoting.Service",
                "ContextBoundRemoting.PrintService");

            Dictionary.Add(clientID, service);

            return service;
        }


        public CrossDomainMarshaller()
        {
        }

        public override object InitializeLifetimeService()
        {
            return null;
        }
    }

    /// <summary>
    /// 
    /// </summary>
    [AttributeUsage(AttributeTargets.Class)]
    class CrossDomainContextAttribute : ContextAttribute
    {
        /// <summary>
        /// 
        /// </summary>
        public CrossDomainContextAttribute() : base("Interception")
        { 
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="ctor"></param>
        /// <returns></returns>
        public override bool IsContextOK(Context context, IConstructionCallMessage ctor)
        {
            // if this is already an intercepting context, it's ok for us
            return (context.GetProperty("Interception") != null);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ctor"></param>
        public override void GetPropertiesForNewContext(IConstructionCallMessage ctor)
        {
            // add the context property which will later create a sink
            ctor.ContextProperties.Add( new CrossDomainContextProperty());
        }
    }

    /// <summary>
    /// 
    /// </summary>
    class CrossDomainContextProperty : 
        IContextProperty,
        IContributeObjectSink
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="newContext"></param>
        /// <returns></returns>
        public bool IsNewContextOK(Context newContext)
        {
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="newContext"></param>
        public void Freeze(Context newContext)
        {
            // nothing to do
        }

        /// <summary>
        /// 
        /// </summary>
        public string Name
        {
            get { return "CrossDomain"; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="nextSink"></param>
        /// <returns></returns>
        public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink)
        {
            return new MessageSink(nextSink);
        }
    }

    /// <summary>
    /// 
    /// </summary>
    class MessageSink :
        IMessageSink
    {
        IMessageSink nextSink;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="nextSink"></param>
        public MessageSink(IMessageSink nextSink)
        {
            this.nextSink = nextSink;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public IMessage SyncProcessMessage(IMessage msg)
        {
            if (msg.Properties["__Uri"] == null)
                return this.nextSink.SyncProcessMessage(msg);
            else
            {
                LogicalCallContext callContext = (LogicalCallContext)msg.Properties["__CallContext"];
                string clientID = (string)callContext.GetData("__ClientID");
                if(clientID != null)
                    return CrossDomainMarshaller.GetService(clientID).Marshal(msg);
                else
                    return new ReturnMessage(
                        new ApplicationException("No __ClientID"),                       
                        (IMethodCallMessage)msg);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="replySink"></param>
        /// <returns></returns>
        public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
        {
            return this.nextSink.AsyncProcessMessage(msg, replySink);
        }

        /// <summary>
        /// 
        /// </summary>
        public IMessageSink NextSink
        {
            get { return this.nextSink; }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Wytek Szymanski
Web Developer
United States United States
I am a consultant, trainer, software archtect/engineer, since the early 1980s, working in the greater area of Boston, MA, USA.

My work comprises the entire spectrum of software, shrink-wrapped applications, IT client-server, systems and protocol related work, compilers and operating systems, and more ....

I am currently focused on platform development for distributed computing in service oriented data centers.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150427.1 | Last Updated 10 Apr 2006
Article Copyright 2006 by Wytek Szymanski
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid