The Labs \ Source Viewer \ SSCLI \ System.Runtime.Remoting.Channels \ IChannelReceiver

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*============================================================
  16. **
  17. ** File:    IChannel.cs
  18. **
  19. **
  20. ** Purpose: Defines the interfaces implemented by channels
  21. **
  22. **
  23. ===========================================================*/
  24. namespace System.Runtime.Remoting.Channels
  25. {
  26.     using System.Collections;
  27.     using System.IO;
  28.     using System.Runtime.Remoting;
  29.     using System.Runtime.Remoting.Messaging;
  30.     using System.Runtime.Remoting.Metadata;
  31.     using System.Security.Permissions;
  32.     using System;
  33.     using System.Globalization;
  34.    
  35.     [System.Runtime.InteropServices.ComVisible(true)]
  36.     public interface IChannel
  37.     {
  38.         int ChannelPriority {
  39.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  40.             get;
  41.         }
  42.         string ChannelName {
  43.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  44.             get;
  45.         }
  46.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  47.         string Parse(string url, out string objectURI);
  48.     }
  49.    
  50.     [System.Runtime.InteropServices.ComVisible(true)]
  51.     public interface IChannelSender : IChannel
  52.     {
  53.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  54.         IMessageSink CreateMessageSink(string url, object remoteChannelData, out string objectURI);
  55.     }
  56.     // interface IChannelSender
  57.     [System.Runtime.InteropServices.ComVisible(true)]
  58.     public interface IChannelReceiver : IChannel
  59.     {
  60.         object ChannelData {
  61.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  62.             get;
  63.         }
  64.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  65.         string[] GetUrlsForUri(string objectURI);
  66.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  67.         void StartListening(object data);
  68.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  69.         void StopListening(object data);
  70.     }
  71.     // interface IChannelReceiver
  72.    
  73.     [System.Runtime.InteropServices.ComVisible(true)]
  74.     public interface IChannelReceiverHook
  75.     {
  76.         string ChannelScheme {
  77.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  78.             get;
  79.         }
  80.        
  81.         bool WantsToListen {
  82.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  83.             get;
  84.         }
  85.        
  86.         IServerChannelSink ChannelSinkChain {
  87.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  88.             get;
  89.         }
  90.        
  91.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  92.         void AddHookChannelUri(string channelUri);
  93.        
  94.     }
  95.     // interface IChannelReceiverHook
  96.     [System.Runtime.InteropServices.ComVisible(true)]
  97.     public interface IClientChannelSinkProvider
  98.     {
  99.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  100.         IClientChannelSink CreateSink(IChannelSender channel, string url, object remoteChannelData);
  101.        
  102.         IClientChannelSinkProvider Next {
  103.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  104.             get;
  105.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  106.             set;
  107.         }
  108.     }
  109.     // interface IClientChannelSinkProvider
  110.    
  111.     [System.Runtime.InteropServices.ComVisible(true)]
  112.     public interface IServerChannelSinkProvider
  113.     {
  114.         // The sink provider should also chain this call to the next provider in the chain.
  115.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  116.         void GetChannelData(IChannelDataStore channelData);
  117.        
  118.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  119.         IServerChannelSink CreateSink(IChannelReceiver channel);
  120.        
  121.         IServerChannelSinkProvider Next {
  122.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  123.             get;
  124.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  125.             set;
  126.         }
  127.     }
  128.     // interface IServerChannelSinkProvider
  129.    
  130.     // This has the same exact functionality as IClientChannelSinkProvider.
  131.     [System.Runtime.InteropServices.ComVisible(true)]
  132.     public interface IClientFormatterSinkProvider : IClientChannelSinkProvider
  133.     {
  134.     }
  135.     // interface IClientFormatterSinkProvider
  136.    
  137.     // This has the same exact functionality as IServerChannelSinkProvider.
  138.     // There may be multiple formatter sinks. If there are more than one, then one
  139.     // formatter sink may decide to delegate the formatting responsibilities to the next
  140.     // one.
  141.     [System.Runtime.InteropServices.ComVisible(true)]
  142.     public interface IServerFormatterSinkProvider : IServerChannelSinkProvider
  143.     {
  144.     }
  145.     // interface IServerFormatterSinkProvider
  146.    
  147.    
  148.     [System.Runtime.InteropServices.ComVisible(true)]
  149.     public interface IClientChannelSink : IChannelSinkBase
  150.     {
  151.         // Parameters:
  152.         // msg - it's the "IMethodCallMessage"
  153.         // requestHeaders - headers to add to the outgoing message heading to server
  154.         // requestStream - stream headed towards the transport sink
  155.         // responseHeaders - headers that server returned
  156.         // responseStream - stream coming back from the transport sink
  157.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  158.         void ProcessMessage(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream, out ITransportHeaders responseHeaders, out Stream responseStream);
  159.        
  160.         // Parameters: (for async calls, the transport sink is responsible for doing the write
  161.         // and read asynchronously)
  162.         // sinkStack - channel sinks who called this one
  163.         // msg - it's the "IMessage" msg
  164.         // headers - headers to add to the outgoing message heading to server
  165.         // stream - stream headed towards the transport sink
  166.         // Returns:
  167.         // IAsyncResult for this call.
  168.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  169.         void AsyncProcessRequest(IClientChannelSinkStack sinkStack, IMessage msg, ITransportHeaders headers, Stream stream);
  170.        
  171.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  172.         void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, object state, ITransportHeaders headers, Stream stream);
  173.        
  174.         // Parameters:
  175.         // msg - it's the "IMethodCallMessage"
  176.         // headers - headers to add to the outgoing message heading to server
  177.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  178.         Stream GetRequestStream(IMessage msg, ITransportHeaders headers);
  179.        
  180.        
  181.         // the next channel sink in the chain
  182.         IClientChannelSink NextChannelSink {
  183.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  184.             get;
  185.         }
  186.        
  187.     }
  188.     // IClientChannelSink
  189.    
  190.    
  191.     [Serializable()]
  192.     [System.Runtime.InteropServices.ComVisible(true)]
  193.     public enum ServerProcessing
  194.     {
  195.         Complete,
  196.         // server synchronously processed message
  197.         OneWay,
  198.         // message dispatched and no response should be sent
  199.         Async
  200.         // the call was dispatched asynchronously
  201.         // (sink should store data on stack for later processing)
  202.     }
  203.     // ServerProcessing
  204.    
  205.     // Used for security sink and transport sinks.
  206.     [System.Runtime.InteropServices.ComVisible(true)]
  207.     public interface IServerChannelSink : IChannelSinkBase
  208.     {
  209.         // Parameters:
  210.         // sinkStack - channel sinks who called this one
  211.         // requestMsg - deserialized request message or null if the stream hasn't been deserialized
  212.         // requestHeaders - headers retrieved from the incoming message from client
  213.         // requestStream - stream to process and pass onto towards the deserialization sink.
  214.         // responseMsg - response message
  215.         // responseHeaders - headers to add to return message heading to client
  216.         // responseStream - stream heading back towards the transport sink
  217.         // Returns:
  218.         // Provides information about how message was processed.
  219.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  220.         ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream);
  221.        
  222.         // Parameters: (for async calls)
  223.         // sinkStack - sink stack (leading back to the server transport sink)
  224.         // headers - headers to add to return message heading to client
  225.         // stream - stream heading back towards the transport sink
  226.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  227.         void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack, object state, IMessage msg, ITransportHeaders headers, Stream stream);
  228.        
  229.         // Parameters:
  230.         // sinkStack - sink stack (leading back to the server transport sink)
  231.         // state - state that had been pushed to the stack by this sink
  232.         // msg - it's the "IMethodCallMessage"
  233.         // headers - headers to put in response message to client
  234.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  235.         Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack, object state, IMessage msg, ITransportHeaders headers);
  236.        
  237.        
  238.         // the next channel sink in the chain
  239.         IServerChannelSink NextChannelSink {
  240.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  241.             get;
  242.         }
  243.        
  244.     }
  245.     // interface IServerChannelSink
  246.    
  247.     [System.Runtime.InteropServices.ComVisible(true)]
  248.     public interface IChannelSinkBase
  249.     {
  250.         // This returns a dictionary through which properties on the sink may be retrieved
  251.         // or configured. If a property is not present in this sink, it should delegate the
  252.         // the property get or set to the next sink in the chain.
  253.         IDictionary Properties {
  254.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  255.             get;
  256.         }
  257.     }
  258.    
  259.    
  260.    
  261.     // Client formatter sinks are both a message sink and a channel sink.
  262.     // They initially transform the message into a stream.
  263.     [System.Runtime.InteropServices.ComVisible(true)]
  264.     public interface IClientFormatterSink : IMessageSink, IClientChannelSink
  265.     {
  266.     }
  267.     // interface IClientFormatterSink
  268.    
  269.    
  270.    
  271.     // Channels wishing to use the channel sink architecture must implement this interface
  272.     // on their ChannelData object.
  273.     [System.Runtime.InteropServices.ComVisible(true)]
  274.     public interface IChannelDataStore
  275.     {
  276.         string[] ChannelUris {
  277.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  278.             get;
  279.         }
  280.        
  281.         object this[object key]
  282.         {
  283.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  284.             get;
  285.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  286.             set;
  287.         }
  288.     }
  289.     // interface IChannelDataStore
  290.    
  291.     // Used to store channel data for our remoting channels
  292.     [Serializable(), SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure), SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  293.     [System.Runtime.InteropServices.ComVisible(true)]
  294.     public class ChannelDataStore : IChannelDataStore
  295.     {
  296.         string[] _channelURIs;
  297.         // list of channel uri's that map to this channel
  298.         DictionaryEntry[] _extraData;
  299.         // sink data
  300.         // private constructor for shallow clone
  301.         private ChannelDataStore(string[] channelUrls, DictionaryEntry[] extraData)
  302.         {
  303.             _channelURIs = channelUrls;
  304.             _extraData = extraData;
  305.         }
  306.        
  307.         public ChannelDataStore(string[] channelURIs)
  308.         {
  309.             _channelURIs = channelURIs;
  310.             _extraData = null;
  311.         }
  312.        
  313.         internal ChannelDataStore InternalShallowCopy()
  314.         {
  315.             return new ChannelDataStore(_channelURIs, _extraData);
  316.         }
  317.        
  318.        
  319.         public string[] ChannelUris {
  320.             get { return _channelURIs; }
  321.             set { _channelURIs = value; }
  322.         }
  323.        
  324.         // implementation of IChannelDataStore
  325.         public object this[object key]
  326.         {
  327.             get {
  328.                 // look for matching key in extra data list
  329.                 foreach (DictionaryEntry entry in _extraData) {
  330.                     if (entry.Key.Equals(key))
  331.                         return entry.Value;
  332.                 }
  333.                
  334.                 // entry not found
  335.                 return null;
  336.             }
  337.             // get
  338.             set {
  339.                 if (_extraData == null) {
  340.                     _extraData = new DictionaryEntry[1];
  341.                     _extraData[0] = new DictionaryEntry(key, value);
  342.                 }
  343.                 else {
  344.                     int length = _extraData.Length;
  345.                     DictionaryEntry[] newList = new DictionaryEntry[length + 1];
  346.                     int co = 0;
  347.                     for (; co < length; co++)
  348.                         newList[co] = _extraData[co];
  349.                     newList[co] = new DictionaryEntry(key, value);
  350.                     // set last value
  351.                     _extraData = newList;
  352.                 }
  353.             }
  354.         }
  355.         // set
  356.         // Object this[Object key]
  357.     }
  358.     // class ChannelDataStore
  359.    
  360.    
  361.    
  362.     [System.Runtime.InteropServices.ComVisible(true)]
  363.     public interface ITransportHeaders
  364.     {
  365.         // Should add headers in order, and remove them if somebody tries to set
  366.         // it to null.
  367.         object this[object key]
  368.         {
  369.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  370.             get;
  371.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  372.             set;
  373.         }
  374.        
  375.         // This is required to handback an enumerator which iterates over all entries
  376.         // in the headers.
  377.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  378.         IEnumerator GetEnumerator();
  379.     }
  380.     // interface ITransportHeaders
  381.    
  382.     // TransportHeaders is used to store a collection of headers that is used in the channel sinks.
  383.     // The header list preserves order, and keeps headers in the order that they were originally
  384.     // added. You can use the foreach statement to iterate over the contents of the header list
  385.     // which contains objects of type DictionaryEntry. Keys are required to be strings, and
  386.     // comparisons are done on a case-insensitive basis.
  387.     [Serializable(), SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure), SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  388.     [System.Runtime.InteropServices.ComVisible(true)]
  389.     public class TransportHeaders : ITransportHeaders
  390.     {
  391.         private ArrayList _headerList;
  392.         // array of type DictionaryEntry
  393.         public TransportHeaders()
  394.         {
  395.             // The default capacity is larger than we'll typically need so start off at 6.
  396.             _headerList = new ArrayList(6);
  397.         }
  398.         // TransportHeaders
  399.        
  400.         // dictionary like interface
  401.         public object this[object key]
  402.         {
  403.             get {
  404.                 string strKey = (string)key;
  405.                
  406.                 // look for matching key in header list
  407.                 foreach (DictionaryEntry entry in _headerList) {
  408.                     if (String.Compare((string)entry.Key, strKey, StringComparison.OrdinalIgnoreCase) == 0)
  409.                         return entry.Value;
  410.                 }
  411.                
  412.                 // entry not found
  413.                 return null;
  414.             }
  415.             // get
  416.             set {
  417.                 if (key == null)
  418.                     return;
  419.                
  420.                 string strKey = (string)key;
  421.                
  422.                 // remove this entry if it's already in the list
  423.                 int co = _headerList.Count - 1;
  424.                 while (co >= 0) {
  425.                     string headerKey = (string)((DictionaryEntry)_headerList[co]).Key;
  426.                     if (String.Compare(headerKey, strKey, StringComparison.OrdinalIgnoreCase) == 0) {
  427.                         _headerList.RemoveAt(co);
  428.                         break;
  429.                     }
  430.                     co--;
  431.                 }
  432.                
  433.                 // otherwise, add this entry
  434.                 if (value != null) {
  435.                     _headerList.Add(new DictionaryEntry(key, value));
  436.                 }
  437.             }
  438.         }
  439.         // set
  440.         // Object this[Object key]
  441.        
  442.         public IEnumerator GetEnumerator()
  443.         {
  444.             return _headerList.GetEnumerator();
  445.         }
  446.         // GetEnumerator
  447.     }
  448.     // TransportHeaders
  449.    
  450.    
  451.     // All sink providers must have a constructor that accepts a hashtable and
  452.     // an ArrayList of these structures if they want to be used from a config file.
  453.     [System.Runtime.InteropServices.ComVisible(true)]
  454.     public class SinkProviderData
  455.     {
  456.         private string _name;
  457.         private Hashtable _properties = new Hashtable(StringComparer.InvariantCultureIgnoreCase);
  458.         private ArrayList _children = new ArrayList();
  459.        
  460.         public SinkProviderData(string name)
  461.         {
  462.             _name = name;
  463.         }
  464.        
  465.         public string Name {
  466.             get { return _name; }
  467.         }
  468.         public IDictionary Properties {
  469.             get { return _properties; }
  470.         }
  471.         public IList Children {
  472.             get { return _children; }
  473.         }
  474.     }
  475.     // class SinkProviderData
  476.    
  477.    
  478.    
  479.    
  480.     // Base implementation for channel sinks that want to supply properties.
  481.     // The derived class only needs to implement the Keys property and this[].
  482.     [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure), SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  483.     [System.Runtime.InteropServices.ComVisible(true)]
  484.     public abstract class BaseChannelSinkWithProperties : BaseChannelObjectWithProperties
  485.     {
  486.         protected BaseChannelSinkWithProperties() : base()
  487.         {
  488.         }
  489.     }
  490.     // class BaseChannelSinkWithProperties
  491.    
  492.     // This provides a base implementation of a channel that wants
  493.     // to provide a dictionary interface. It handles the complexity
  494.     // of asking a channel sink chain for their properties.
  495.     // Once the channel constructs its sink chain (usually only applicable
  496.     // for server channels) it should set the SinksWithProperties property.
  497.     // The properties only get chained for channel sinks when the users asks
  498.     // for the "Properties" dictionary. If you just go through the dictionary interface
  499.     // you'll only get the channel specific properties.
  500.     // The derived class only needs to implement the Keys property and this[].
  501.     [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure), SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  502.     [System.Runtime.InteropServices.ComVisible(true)]
  503.     public abstract class BaseChannelWithProperties : BaseChannelObjectWithProperties
  504.     {
  505.         protected IChannelSinkBase SinksWithProperties = null;
  506.        
  507.         protected BaseChannelWithProperties() : base()
  508.         {
  509.         }
  510.        
  511.         // This is overridden so that server channels can expose the properties
  512.         // of their channel sinks through a flat dictionary interface.
  513.         public override IDictionary Properties {
  514.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  515.             get {
  516.                 // collect dictionaries for all channel sinks and return
  517.                 // aggregate dictionary
  518.                 ArrayList dictionaries = new ArrayList();
  519.                
  520.                 // add the channel itself
  521.                 dictionaries.Add(this);
  522.                
  523.                 if (SinksWithProperties != null) {
  524.                     IServerChannelSink srvSink = SinksWithProperties as IServerChannelSink;
  525.                     if (srvSink != null) {
  526.                         while (srvSink != null) {
  527.                             IDictionary dict = srvSink.Properties;
  528.                             if (dict != null)
  529.                                 dictionaries.Add(dict);
  530.                            
  531.                             srvSink = srvSink.NextChannelSink;
  532.                         }
  533.                     }
  534.                     else {
  535.                         // we know it's a client channel sink
  536.                         IClientChannelSink chnlSink = (IClientChannelSink)SinksWithProperties;
  537.                        
  538.                         while (chnlSink != null) {
  539.                             IDictionary dict = chnlSink.Properties;
  540.                             if (dict != null)
  541.                                 dictionaries.Add(dict);
  542.                            
  543.                             chnlSink = chnlSink.NextChannelSink;
  544.                         }
  545.                     }
  546.                 }
  547.                
  548.                 // return a dictionary that spans all dictionaries provided
  549.                 return new AggregateDictionary(dictionaries);
  550.             }
  551.         }
  552.        
  553.     }
  554.     // class BaseChannelWithProperties
  555.    
  556.    
  557.    
  558.    
  559.    
  560.    
  561.     // Base implementation for channel sinks that want to supply properties.
  562.     // The derived class only needs to implement the Keys property and this[].
  563.     [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure), SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  564.     [System.Runtime.InteropServices.ComVisible(true)]
  565.     public abstract class BaseChannelObjectWithProperties : IDictionary
  566.     {
  567.         protected BaseChannelObjectWithProperties()
  568.         {
  569.         }
  570.        
  571.         public virtual IDictionary Properties {
  572.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  573.             get { return this; }
  574.         }
  575.        
  576.         //
  577.         // IDictionary implementation
  578.         //
  579.        
  580.         public virtual object this[object key]
  581.         {
  582.             get { return null; }
  583.             set {
  584.                 throw new NotImplementedException();
  585.             }
  586.         }
  587.         // Object this[Object key]
  588.         public virtual ICollection Keys {
  589.             get { return null; }
  590.         }
  591.        
  592.         public virtual ICollection Values {
  593.             get {
  594.                 ICollection keys = Keys;
  595.                 if (keys == null)
  596.                     return null;
  597.                
  598.                 ArrayList values = new ArrayList();
  599.                 foreach (object key in keys) {
  600.                     values.Add(this[key]);
  601.                 }
  602.                
  603.                 return values;
  604.             }
  605.         }
  606.        
  607.         public virtual bool Contains(object key)
  608.         {
  609.             if (key == null)
  610.                 return false;
  611.            
  612.             ICollection keySet = Keys;
  613.             if (keySet == null)
  614.                 return false;
  615.            
  616.             string keyStr = key as string;
  617.            
  618.             foreach (object someKey in keySet) {
  619.                 if (keyStr != null) {
  620.                     string someKeyStr = someKey as string;
  621.                     if (someKeyStr != null) {
  622.                         // compare the key strings case-insensitively
  623.                         if (String.Compare(keyStr, someKeyStr, StringComparison.OrdinalIgnoreCase) == 0)
  624.                             return true;
  625.                        
  626.                         continue;
  627.                     }
  628.                 }
  629.                
  630.                 if (key.Equals(someKey))
  631.                     return true;
  632.             }
  633.            
  634.             return false;
  635.         }
  636.         // Contains
  637.         public virtual bool IsReadOnly {
  638.             get { return false; }
  639.         }
  640.         public virtual bool IsFixedSize {
  641.             get { return true; }
  642.         }
  643.        
  644.         // The following three methods should never be implemented because
  645.         // they don't apply to the way IDictionary is being used in this case
  646.         // (plus, IsFixedSize returns true.)
  647.         public virtual void Add(object key, object value)
  648.         {
  649.             throw new NotSupportedException();
  650.         }
  651.         public virtual void Clear()
  652.         {
  653.             throw new NotSupportedException();
  654.         }
  655.         public virtual void Remove(object key)
  656.         {
  657.             throw new NotSupportedException();
  658.         }
  659.        
  660.         public virtual IDictionaryEnumerator GetEnumerator()
  661.         {
  662.             return new DictionaryEnumeratorByKeys(this);
  663.         }
  664.         // GetEnumerator
  665.        
  666.         //
  667.         // end of IDictionary implementation
  668.         //
  669.        
  670.         //
  671.         // ICollection implementation
  672.         //
  673.        
  674.         //ICollection
  675.        
  676.         public virtual void CopyTo(Array array, int index)
  677.         {
  678.             throw new NotSupportedException();
  679.         }
  680.        
  681.         public virtual int Count {
  682.             get {
  683.                 ICollection keySet = Keys;
  684.                 if (keySet == null)
  685.                     return 0;
  686.                
  687.                 return keySet.Count;
  688.             }
  689.         }
  690.         // Count
  691.         public virtual object SyncRoot {
  692.             get { return this; }
  693.         }
  694.         public virtual bool IsSynchronized {
  695.             get { return false; }
  696.         }
  697.        
  698.         //
  699.         // end of ICollection implementation
  700.         //
  701.        
  702.         //IEnumerable
  703.         /// <internalonly/>
  704.         IEnumerator IEnumerable.GetEnumerator()
  705.         {
  706.             return new DictionaryEnumeratorByKeys(this);
  707.         }
  708.        
  709.     }
  710.     // class BaseChannelObjectWithProperties
  711.    
  712.    
  713.     // an enumerator based off of a key set
  714.     internal class DictionaryEnumeratorByKeys : IDictionaryEnumerator
  715.     {
  716.         IDictionary _properties;
  717.         IEnumerator _keyEnum;
  718.        
  719.         public DictionaryEnumeratorByKeys(IDictionary properties)
  720.         {
  721.             _properties = properties;
  722.             _keyEnum = properties.Keys.GetEnumerator();
  723.         }
  724.         // PropertyEnumeratorByKeys
  725.         public bool MoveNext()
  726.         {
  727.             return _keyEnum.MoveNext();
  728.         }
  729.         public void Reset()
  730.         {
  731.             _keyEnum.Reset();
  732.         }
  733.         public object Current {
  734.             get { return Entry; }
  735.         }
  736.        
  737.         public DictionaryEntry Entry {
  738.             get { return new DictionaryEntry(Key, Value); }
  739.         }
  740.        
  741.         public object Key {
  742.             get { return _keyEnum.Current; }
  743.         }
  744.         public object Value {
  745.             get { return _properties[Key]; }
  746.         }
  747.        
  748.     }
  749.     // DictionaryEnumeratorByKeys
  750.    
  751.     // combines multiple dictionaries into one
  752.     // (used for channel sink properties
  753.     internal class AggregateDictionary : IDictionary
  754.     {
  755.         private ICollection _dictionaries;
  756.        
  757.         public AggregateDictionary(ICollection dictionaries)
  758.         {
  759.             _dictionaries = dictionaries;
  760.         }
  761.         // AggregateDictionary
  762.         //
  763.         // IDictionary implementation
  764.         //
  765.        
  766.         public virtual object this[object key]
  767.         {
  768.             get {
  769.                 foreach (IDictionary dict in _dictionaries) {
  770.                     if (dict.Contains(key))
  771.                         return dict[key];
  772.                 }
  773.                
  774.                 return null;
  775.             }
  776.            
  777.             set {
  778.                 foreach (IDictionary dict in _dictionaries) {
  779.                     if (dict.Contains(key))
  780.                         dict[key] = value;
  781.                 }
  782.             }
  783.         }
  784.         // Object this[Object key]
  785.         public virtual ICollection Keys {
  786.             get {
  787.                 ArrayList keys = new ArrayList();
  788.                 // add keys from every dictionary
  789.                 foreach (IDictionary dict in _dictionaries) {
  790.                     ICollection dictKeys = dict.Keys;
  791.                     if (dictKeys != null) {
  792.                         foreach (object key in dictKeys) {
  793.                             keys.Add(key);
  794.                         }
  795.                     }
  796.                 }
  797.                
  798.                 return keys;
  799.             }
  800.         }
  801.         // Keys
  802.         public virtual ICollection Values {
  803.             get {
  804.                 ArrayList values = new ArrayList();
  805.                 // add values from every dictionary
  806.                 foreach (IDictionary dict in _dictionaries) {
  807.                     ICollection dictValues = dict.Values;
  808.                     if (dictValues != null) {
  809.                         foreach (object value in dictValues) {
  810.                             values.Add(value);
  811.                         }
  812.                     }
  813.                 }
  814.                
  815.                 return values;
  816.             }
  817.         }
  818.         // Values
  819.         public virtual bool Contains(object key)
  820.         {
  821.             foreach (IDictionary dict in _dictionaries) {
  822.                 if (dict.Contains(key))
  823.                     return true;
  824.             }
  825.            
  826.             return false;
  827.         }
  828.         // Contains
  829.         public virtual bool IsReadOnly {
  830.             get { return false; }
  831.         }
  832.         public virtual bool IsFixedSize {
  833.             get { return true; }
  834.         }
  835.        
  836.         // The following three methods should never be implemented because
  837.         // they don't apply to the way IDictionary is being used in this case
  838.         // (plus, IsFixedSize returns true.)
  839.         public virtual void Add(object key, object value)
  840.         {
  841.             throw new NotSupportedException();
  842.         }
  843.         public virtual void Clear()
  844.         {
  845.             throw new NotSupportedException();
  846.         }
  847.         public virtual void Remove(object key)
  848.         {
  849.             throw new NotSupportedException();
  850.         }
  851.        
  852.         public virtual IDictionaryEnumerator GetEnumerator()
  853.         {
  854.             return new DictionaryEnumeratorByKeys(this);
  855.         }
  856.         // GetEnumerator
  857.        
  858.         //
  859.         // end of IDictionary implementation
  860.         //
  861.        
  862.         //
  863.         // ICollection implementation
  864.         //
  865.        
  866.         //ICollection
  867.        
  868.         public virtual void CopyTo(Array array, int index)
  869.         {
  870.             throw new NotSupportedException();
  871.         }
  872.        
  873.         public virtual int Count {
  874.             get {
  875.                 int count = 0;
  876.                
  877.                 foreach (IDictionary dict in _dictionaries) {
  878.                     count += dict.Count;
  879.                 }
  880.                
  881.                 return count;
  882.             }
  883.         }
  884.         // Count
  885.         public virtual object SyncRoot {
  886.             get { return this; }
  887.         }
  888.         public virtual bool IsSynchronized {
  889.             get { return false; }
  890.         }
  891.        
  892.         //
  893.         // end of ICollection implementation
  894.         //
  895.        
  896.         //IEnumerable
  897.         IEnumerator IEnumerable.GetEnumerator()
  898.         {
  899.             return new DictionaryEnumeratorByKeys(this);
  900.         }
  901.        
  902.     }
  903.     // class AggregateDictionary
  904.    
  905.    
  906. }
  907. // namespace System.Runtime.Remoting

Developer Fusion