class Program
{
  static void Main ()
  {
    AppDomain newDomain = AppDomain.CreateDomain ("Nowa domena");
    newDomain.DoCallBack (new CrossAppDomainDelegate (SayHello));
    AppDomain.Unload (newDomain);
  }

  static void SayHello()
  {
    Console.WriteLine ("Witaj z domeny " + AppDomain.CurrentDomain.FriendlyName);
  }
}

--------------------------------------------------------------------------------

class Program
{
  static void Main()
  { 
    // utworzenie 20 domen i 20 wątków
    AppDomain[] domains = new AppDomain [20];
    Thread[] threads = new Thread [20];

    for (int i = 0; i < 20; i++)
    {
      domains [i] = AppDomain.CreateDomain ("Login klienta " + i);
      threads [i] = new Thread (LoginOtherDomain);
    }

    // uruchomienie wszystkich wątków z przekazaniem każdemu osobnej domeny aplikacji
    for (int i = 0; i < 20; i++) threads [i].Start (domains [i]);

    // czekanie, aż wszystkie wątki skończą pracę
    for (int i = 0; i < 20; i++) threads [i].Join();

    // usunięcie domen aplikacji
    for (int i = 0; i < 20; i++) AppDomain.Unload (domains [i]);
    Console.ReadLine();
  }

  // uruchomienie wątku z parametrami — przekazanie domeny do działania
  static void LoginOtherDomain (object domain)
  {
     ((AppDomain) domain).DoCallBack (Login);
  }

  static void Login()
  {
    Client.Login ("Jan", "");
    Console.WriteLine ("Zalogowano jako: " + Client.CurrentUser + " przy użyciu " +
    AppDomain.CurrentDomain.FriendlyName);
  }
}

class Client
{
  // to jest statyczne pole, które przeszkadzałoby przy logowaniu innych klientów,
  // gdyby operacja odbywała się w tej samej domenie aplikacji
  public static string CurrentUser = "";

  public static void Login (string name, string password)
  {
    if (CurrentUser.Length == 0) // jeśli jeszcze nie jesteśmy zalogowani...
    {
      // uśpienie w celu symulacji uwierzytelniania...
      Thread.Sleep (500);
      CurrentUser = name; // zarejestrowanie uwierzytelnienia
    }
  }
}

--------------------------------------------------------------------------------

class Program
{
  static void Main()
  {
    AppDomain newDomain = AppDomain.CreateDomain ("New Domain");

    // Write to a named slot called "Message" – any string key will do.
    newDomain.SetData ("Message", "guess what...");

    newDomain.DoCallBack (SayMessage);
    AppDomain.Unload (newDomain);
  }

  static void SayMessage()
  {
    // Read from the "Message" data slot
    Console.WriteLine (AppDomain.CurrentDomain.GetData ("Message"));
  }
}

--------------------------------------------------------------------------------

class Program
{
  static void Main()
  {
    AppDomain newDomain = AppDomain.CreateDomain ("Nowa domena");

    // zapis w komórce o nazwie Message — kluczem może być dowolny łańcuch
    newDomain.SetData ("Message", "zgadnij, co...");

    newDomain.DoCallBack (SayMessage);
    AppDomain.Unload (newDomain);
  }

  static void SayMessage()
  {
    // odczyt z komórki o nazwie Message
    Console.WriteLine (AppDomain.CurrentDomain.GetData ("Message"));
  }
}


--------------------------------------------------------------------------------

namespace Plugin.Common
{
  public interface ITextPlugin
  {
    string TransformText (string input);
  }
}

--------------------------------------------------------------------------------
namespace Plugin.Extensions
{
  public class AllCapitals : MarshalByRefObject, Plugin.Common.ITextPlugin
  {
    public string TransformText (string input) { return input.ToUpper(); }
  }
}

--------------------------------------------------------------------------------
using System;
using System.Reflection;
using Plugin.Common;

class Program
{
  static void Main()
  {
    AppDomain domain = AppDomain.CreateDomain ("Domena wtyczki");

    ITextPlugin plugin = (ITextPlugin) domain.CreateInstanceFromAndUnwrap
      ("AllCapitals.dll", "Plugin.Extensions.AllCapitals");

    // wywołanie metody TransformText przy użyciu technologii Remoting
    Console.WriteLine (plugin.TransformText ("cześć")); // CZEŚĆ

    AppDomain.Unload (domain);

    // w tym momencie plik AllCapitals.dll jest już usunięty z pamięci i
    // może zostać przeniesiony lub skasowany
  }
}

--------------------------------------------------------------------------------

public class Discoverer : MarshalByRefObject
{
  public string[] GetPluginTypeNames (string assemblyPath)
  {
    List<string> typeNames = new List<string> ();
    Assembly a = Assembly.LoadFrom (assemblyPath);
    foreach (Type t in a.GetTypes ())
    if (t.IsPublic
        && t.IsMarshalByRef 
        && typeof (ITextPlugin).IsAssignableFrom (t))
    {
      typeNames.Add (t.FullName);
    }
    return typeNames.ToArray ();
  }
}

--------------------------------------------------------------------------------
class Program 
{
  static void Main()
  {
    AppDomain domain = AppDomain.CreateDomain ("Domena aplikacji");

    Discoverer d = (Discoverer) domain.CreateInstanceAndUnwrap (
      typeof (Discoverer).Assembly.FullName,
      typeof (Discoverer).FullName);

    string[] plugInTypeNames = d.GetPluginTypeNames ("AllCapitals.dll");

    foreach (string s in plugInTypeNames)
      Console.WriteLine (s);              // Plugin.Extensions.AllCapitals
      ...
