//
// System.Runtime.Remoting.RemotingConfiguration.cs
//
// Author: Jaime Anguiano Olarra (jaime@gnome.org)
// Lluis Sanchez Gual (lluis@ideary.com)
//
// (C) 2002, Jaime Anguiano Olarra
//
//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Collections;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Lifetime;
using Mono.Xml;
namespace System.Runtime.Remoting{
[System.Runtime.InteropServices.ComVisible (true)]
public static class RemotingConfiguration
{
static string applicationID = null;
static string applicationName = null;
// static string configFile = "";
// static SmallXmlParser parser = null;
static string processGuid = null;
static bool defaultConfigRead = false;
static bool defaultDelayedConfigRead = false;
static string _errorMode;
static Hashtable wellKnownClientEntries = new Hashtable();
static Hashtable activatedClientEntries = new Hashtable();
static Hashtable wellKnownServiceEntries = new Hashtable();
static Hashtable activatedServiceEntries = new Hashtable();
static Hashtable channelTemplates = new Hashtable ();
static Hashtable clientProviderTemplates = new Hashtable ();
static Hashtable serverProviderTemplates = new Hashtable ();
// public properties
// At this time the ID will be the application name
public static string ApplicationId
{
get
{
applicationID = ApplicationName;
return applicationID;
}
}
public static string ApplicationName
{
get { return applicationName; }
set { applicationName = value; }
}
[MonoTODO]
public static CustomErrorsModes CustomErrorsMode
{
get { throw new NotImplementedException (); }
set { throw new NotImplementedException (); }
}
public static string ProcessId
{
get {
if (processGuid == null)
processGuid = AppDomain.GetProcessGuid ();
return processGuid;
}
}
// public methods
[MonoTODO ("ensureSecurity support has not been implemented")]
public static void Configure (string filename, bool ensureSecurity)
{
lock (channelTemplates) {
if (!defaultConfigRead) {
ReadConfigFile (Environment.GetMachineConfigPath ());
defaultConfigRead = true;
}
if (filename != null)
ReadConfigFile (filename);
}
}
[Obsolete ("Use Configure(String,Boolean)")]
public static void Configure (string filename)
{
Configure (filename, false);
}
private static void ReadConfigFile (string filename)
{
try
{
SmallXmlParser parser = new SmallXmlParser ();
using (TextReader rreader = new StreamReader (filename)) {
ConfigHandler handler = new ConfigHandler (false);
parser.Parse (rreader, handler);
}
}
catch (Exception ex)
{
throw new RemotingException ("Configuration file '" + filename + "' could not be loaded: " + ex.Message, ex);
}
}
internal static void LoadDefaultDelayedChannels ()
{
lock (channelTemplates)
{
if (defaultDelayedConfigRead || defaultConfigRead) return;
SmallXmlParser parser = new SmallXmlParser ();
using (TextReader rreader = new StreamReader (Environment.GetMachineConfigPath ())) {
ConfigHandler handler = new ConfigHandler (true);
parser.Parse (rreader, handler);
}
defaultDelayedConfigRead = true;
}
}
public static ActivatedClientTypeEntry[] GetRegisteredActivatedClientTypes ()
{
lock (channelTemplates)
{
ActivatedClientTypeEntry[] entries = new ActivatedClientTypeEntry[activatedClientEntries.Count];
activatedClientEntries.Values.CopyTo (entries,0);
return entries;
}
}
public static ActivatedServiceTypeEntry[] GetRegisteredActivatedServiceTypes ()
{
lock (channelTemplates)
{
ActivatedServiceTypeEntry[] entries = new ActivatedServiceTypeEntry[activatedServiceEntries.Count];
activatedServiceEntries.Values.CopyTo (entries,0);
return entries;
}
}
public static WellKnownClientTypeEntry[] GetRegisteredWellKnownClientTypes ()
{
lock (channelTemplates)
{
WellKnownClientTypeEntry[] entries = new WellKnownClientTypeEntry[wellKnownClientEntries.Count];
wellKnownClientEntries.Values.CopyTo (entries,0);
return entries;
}
}
public static WellKnownServiceTypeEntry[] GetRegisteredWellKnownServiceTypes ()
{
lock (channelTemplates)
{
WellKnownServiceTypeEntry[] entries = new WellKnownServiceTypeEntry[wellKnownServiceEntries.Count];
wellKnownServiceEntries.Values.CopyTo (entries,0);
return entries;
}
}
public static bool IsActivationAllowed (Type svrType)
{
lock (channelTemplates)
{
return activatedServiceEntries.ContainsKey (svrType);
}
}
public static ActivatedClientTypeEntry IsRemotelyActivatedClientType (Type svrType)
{
lock (channelTemplates)
{
return activatedClientEntries [svrType] as ActivatedClientTypeEntry;
}
}
public static ActivatedClientTypeEntry IsRemotelyActivatedClientType (string typeName, string assemblyName)
{
return IsRemotelyActivatedClientType (Assembly.Load(assemblyName).GetType (typeName));
}
public static WellKnownClientTypeEntry IsWellKnownClientType (Type svrType)
{
lock (channelTemplates)
{
return wellKnownClientEntries [svrType] as WellKnownClientTypeEntry;
}
}
public static WellKnownClientTypeEntry IsWellKnownClientType (string typeName, string assemblyName)
{
return IsWellKnownClientType (Assembly.Load(assemblyName).GetType (typeName));
}
public static void RegisterActivatedClientType (ActivatedClientTypeEntry entry)
{
lock (channelTemplates)
{
if (wellKnownClientEntries.ContainsKey (entry.ObjectType) || activatedClientEntries.ContainsKey (entry.ObjectType))
throw new RemotingException ("Attempt to redirect activation of type '" + entry.ObjectType.FullName + "' which is already redirected.");
activatedClientEntries[entry.ObjectType] = entry;
ActivationServices.EnableProxyActivation (entry.ObjectType, true);
}
}
public static void RegisterActivatedClientType (Type type, string appUrl)
{
if (type == null) throw new ArgumentNullException ("type");
if (appUrl == null) throw new ArgumentNullException ("appUrl");
RegisterActivatedClientType (new ActivatedClientTypeEntry (type, appUrl));
}
public static void RegisterActivatedServiceType (ActivatedServiceTypeEntry entry)
{
lock (channelTemplates)
{
activatedServiceEntries.Add (entry.ObjectType, entry);
}
}
public static void RegisterActivatedServiceType (Type type)
{
RegisterActivatedServiceType (new ActivatedServiceTypeEntry (type));
}
public static void RegisterWellKnownClientType (Type type, string objectUrl)
{
if (type == null) throw new ArgumentNullException ("type");
if (objectUrl == null) throw new ArgumentNullException ("objectUrl");
RegisterWellKnownClientType (new WellKnownClientTypeEntry (type, objectUrl));
}
public static void RegisterWellKnownClientType (WellKnownClientTypeEntry entry)
{
lock (channelTemplates)
{
if (wellKnownClientEntries.ContainsKey (entry.ObjectType) || activatedClientEntries.ContainsKey (entry.ObjectType))
throw new RemotingException ("Attempt to redirect activation of type '" + entry.ObjectType.FullName + "' which is already redirected.");
wellKnownClientEntries[entry.ObjectType] = entry;
ActivationServices.EnableProxyActivation (entry.ObjectType, true);
}
}
public static void RegisterWellKnownServiceType (Type type, string objectUri, WellKnownObjectMode mode)
{
RegisterWellKnownServiceType (new WellKnownServiceTypeEntry (type, objectUri, mode));
}
public static void RegisterWellKnownServiceType (WellKnownServiceTypeEntry entry)
{
lock (channelTemplates)
{
wellKnownServiceEntries [entry.ObjectUri] = entry;
RemotingServices.CreateWellKnownServerIdentity (entry.ObjectType, entry.ObjectUri, entry.Mode);
}
}
internal static void RegisterChannelTemplate (ChannelData channel)
{
channelTemplates [channel.Id] = channel;
}
internal static void RegisterClientProviderTemplate (ProviderData prov)
{
clientProviderTemplates [prov.Id] = prov;
}
internal static void RegisterServerProviderTemplate (ProviderData prov)
{
serverProviderTemplates [prov.Id] = prov;
}
internal static void RegisterChannels (ArrayList channels, bool onlyDelayed)
{
foreach (ChannelData channel in channels)
{
if (onlyDelayed && channel.DelayLoadAsClientChannel != "true")
continue;
if (defaultDelayedConfigRead && channel.DelayLoadAsClientChannel == "true")
continue;
if (channel.Ref != null)
{
ChannelData template = (ChannelData) channelTemplates [channel.Ref];
if (template == null) throw new RemotingException ("Channel template '" + channel.Ref + "' not found");
channel.CopyFrom (template);
}
foreach (ProviderData prov in channel.ServerProviders)
{
if (prov.Ref != null)
{
ProviderData template = (ProviderData) serverProviderTemplates [prov.Ref];
if (template == null) throw new RemotingException ("Provider template '" + prov.Ref + "' not found");
prov.CopyFrom (template);
}
}
foreach (ProviderData prov in channel.ClientProviders)
{
if (prov.Ref != null)
{
ProviderData template = (ProviderData) clientProviderTemplates [prov.Ref];
if (template == null) throw new RemotingException ("Provider template '" + prov.Ref + "' not found");
prov.CopyFrom (template);
}
}
ChannelServices.RegisterChannelConfig (channel);
}
}
internal static void RegisterTypes (ArrayList types)
{
foreach (TypeEntry type in types)
{
if (type is ActivatedClientTypeEntry)
RegisterActivatedClientType ((ActivatedClientTypeEntry)type);
else if (type is ActivatedServiceTypeEntry)
RegisterActivatedServiceType ((ActivatedServiceTypeEntry)type);
else if (type is WellKnownClientTypeEntry)
RegisterWellKnownClientType ((WellKnownClientTypeEntry)type);
else if (type is WellKnownServiceTypeEntry)
RegisterWellKnownServiceType ((WellKnownServiceTypeEntry)type);
}
}
#if NET_1_1
public static bool CustomErrorsEnabled (bool isLocalRequest)
{
if (_errorMode == "off") return false;
if (_errorMode == "on") return true;
return !isLocalRequest;
}
#endif
internal static void SetCustomErrorsMode (string mode)
{
if (mode == null)
throw new RemotingException ("mode attribute is required");
// the mode is case insensitive
string m = mode.ToLower ();
if (m != "on" && m != "off" && m != "remoteonly")
throw new RemotingException ("Invalid custom error mode: " + mode);
_errorMode = m;
}
}
/***************************************************************
* Internal classes used by RemotingConfiguration.Configure () *
***************************************************************/
internal class ConfigHandler : SmallXmlParser.IContentHandler
{
ArrayList typeEntries = new ArrayList ();
ArrayList channelInstances = new ArrayList ();
ChannelData currentChannel = null;
Stack currentProviderData = null;
string currentClientUrl = null;
string appName;
string currentXmlPath = "";
bool onlyDelayedChannels;
public ConfigHandler (bool onlyDelayedChannels)
{
this.onlyDelayedChannels = onlyDelayedChannels;
}
void ValidatePath (string element, params string[] paths)
{
foreach (string path in paths)
if (CheckPath (path)) return;
throw new RemotingException ("Element " + element + " not allowed in this context");
}
bool CheckPath (string path)
{
CompareInfo ci = CultureInfo.InvariantCulture.CompareInfo;
if (ci.IsPrefix (path, "/", CompareOptions.Ordinal))
return path == currentXmlPath;
else
return ci.IsSuffix (currentXmlPath, path, CompareOptions.Ordinal);
}
public void OnStartParsing (SmallXmlParser parser) {}
public void OnProcessingInstruction (string name, string text) {}
public void OnIgnorableWhitespace (string s) {}
public void OnStartElement (string name, SmallXmlParser.IAttrList attrs)
{
try
{
if (currentXmlPath.StartsWith ("/configuration/system.runtime.remoting"))
ParseElement (name, attrs);
currentXmlPath += "/" + name;
}
catch (Exception ex)
{
throw new RemotingException ("Error in element " + name + ": " + ex.Message, ex);
}
}
public void ParseElement (string name, SmallXmlParser.IAttrList attrs)
{
if (currentProviderData != null)
{
ReadCustomProviderData (name, attrs);
return;
}
switch (name)
{
case "application":
ValidatePath (name, "system.runtime.remoting");
if (attrs.Names.Length > 0)
appName = attrs.Values[0];
break;
case "lifetime":
ValidatePath (name, "application");
ReadLifetine (attrs);
break;
case "channels":
ValidatePath (name, "system.runtime.remoting", "application");
break;
case "channel":
ValidatePath (name, "channels");
if (currentXmlPath.IndexOf ("application") != -1)
ReadChannel (attrs, false);
else
ReadChannel (attrs, true);
break;
case "serverProviders":
ValidatePath (name, "channelSinkProviders", "channel");
break;
case "clientProviders":
ValidatePath (name, "channelSinkProviders", "channel");
break;
case "provider":
case "formatter":
ProviderData prov;
if (CheckPath ("application/channels/channel/serverProviders") ||
CheckPath ("channels/channel/serverProviders"))
{
prov = ReadProvider (name, attrs, false);
currentChannel.ServerProviders.Add (prov);
}
else if (CheckPath ("application/channels/channel/clientProviders") ||
CheckPath ("channels/channel/clientProviders"))
{
prov = ReadProvider (name, attrs, false);
currentChannel.ClientProviders.Add (prov);
}
else if (CheckPath ("channelSinkProviders/serverProviders"))
{
prov = ReadProvider (name, attrs, true);
RemotingConfiguration.RegisterServerProviderTemplate (prov);
}
else if (CheckPath ("channelSinkProviders/clientProviders"))
{
prov = ReadProvider (name, attrs, true);
RemotingConfiguration.RegisterClientProviderTemplate (prov);
}
else
ValidatePath (name);
break;
case "client":
ValidatePath (name, "application");
currentClientUrl = attrs.GetValue ("url");
break;
case "service":
ValidatePath (name, "application");
break;
case "wellknown":
ValidatePath (name, "client", "service");
if (CheckPath ("client"))
ReadClientWellKnown (attrs);
else
ReadServiceWellKnown (attrs);
break;
case "activated":
ValidatePath (name, "client", "service");
if (CheckPath ("client"))
ReadClientActivated (attrs);
else
ReadServiceActivated (attrs);
break;
case "soapInterop":
ValidatePath (name, "application");
break;
case "interopXmlType":
ValidatePath (name, "soapInterop");
ReadInteropXml (attrs, false);
break;
case "interopXmlElement":
ValidatePath (name, "soapInterop");
ReadInteropXml (attrs, false);
break;
case "preLoad":
ValidatePath (name, "soapInterop");
ReadPreload (attrs);
break;
case "debug":
ValidatePath (name, "system.runtime.remoting");
break;
case "channelSinkProviders":
ValidatePath (name, "system.runtime.remoting");
break;
case "customErrors":
ValidatePath (name, "system.runtime.remoting");
RemotingConfiguration.SetCustomErrorsMode (attrs.GetValue ("mode"));
break;
default:
throw new RemotingException ("Element '" + name + "' is not valid in system.remoting.configuration section");
}
}
public void OnEndElement (string name)
{
if (currentProviderData != null)
{
currentProviderData.Pop ();
if (currentProviderData.Count == 0)
currentProviderData = null;
}
currentXmlPath = currentXmlPath.Substring (0, currentXmlPath.Length - name.Length - 1);
}
void ReadCustomProviderData (string name, SmallXmlParser.IAttrList attrs)
{
SinkProviderData parent = (SinkProviderData) currentProviderData.Peek ();
SinkProviderData data = new SinkProviderData (name);
for (int i=0; i < attrs.Names.Length; ++i)
data.Properties [attrs.Names[i]] = attrs.GetValue (i);
parent.Children.Add (data);
currentProviderData.Push (data);
}
void ReadLifetine (SmallXmlParser.IAttrList attrs)
{
for (int i=0; i < attrs.Names.Length; ++i) {
switch (attrs.Names[i]) {
case "leaseTime":
LifetimeServices.LeaseTime = ParseTime (attrs.GetValue(i));
break;
case "sponsorshipTimeout":
LifetimeServices.SponsorshipTimeout = ParseTime (attrs.GetValue(i));
break;
case "renewOnCallTime":
LifetimeServices.RenewOnCallTime = ParseTime (attrs.GetValue(i));
break;
case "leaseManagerPollTime":
LifetimeServices.LeaseManagerPollTime = ParseTime (attrs.GetValue(i));
break;
default:
throw new RemotingException ("Invalid attribute: " + attrs.Names[i]);
}
}
}
TimeSpan ParseTime (string s)
{
if (s == "" || s == null) throw new RemotingException ("Invalid time value");
int i = s.IndexOfAny (new char[] { 'D','H','M','S' });
string unit;
if (i == -1)
unit = "S";
else {
unit = s.Substring (i);
s = s.Substring (0,i);
}
double val;
try {
val = double.Parse (s);
}
catch {
throw new RemotingException ("Invalid time value: " + s);
}
if (unit == "D") return TimeSpan.FromDays (val);
if (unit == "H") return TimeSpan.FromHours (val);
if (unit == "M") return TimeSpan.FromMinutes (val);
if (unit == "S") return TimeSpan.FromSeconds (val);
if (unit == "MS") return TimeSpan.FromMilliseconds (val);
throw new RemotingException ("Invalid time unit: " + unit);
}
void ReadChannel (SmallXmlParser.IAttrList attrs, bool isTemplate)
{
ChannelData channel = new ChannelData ();
for (int i=0; i < attrs.Names.Length; ++i)
{
string at = attrs.Names[i];
string val = attrs.Values[i];
if (at == "ref" && !isTemplate)
channel.Ref = val;
else if (at == "delayLoadAsClientChannel")
channel.DelayLoadAsClientChannel = val;
else if (at == "id" && isTemplate)
channel.Id = val;
else if (at == "type")
channel.Type = val;
else
channel.CustomProperties.Add (at, val);
}
if (isTemplate)
{
if (channel.Id == null) throw new RemotingException ("id attribute is required");
if (channel.Type == null) throw new RemotingException ("id attribute is required");
RemotingConfiguration.RegisterChannelTemplate (channel);
}
else
channelInstances.Add (channel);
currentChannel = channel;
}
ProviderData ReadProvider (string name, SmallXmlParser.IAttrList attrs, bool isTemplate)
{
ProviderData prov = (name == "provider") ? new ProviderData () : new FormatterData ();
SinkProviderData data = new SinkProviderData ("root");
prov.CustomData = data.Children;
currentProviderData = new Stack ();
currentProviderData.Push (data);
for (int i=0; i < attrs.Names.Length; ++i)
{
string at = attrs.Names[i];
string val = attrs.Values[i];
if (at == "id" && isTemplate)
prov.Id = val;
else if (at == "type")
prov.Type = val;
else if (at == "ref" && !isTemplate)
prov.Ref = val;
else
prov.CustomProperties.Add (at, val);
}
if (prov.Id == null && isTemplate) throw new RemotingException ("id attribute is required");
return prov;
}
void ReadClientActivated (SmallXmlParser.IAttrList attrs)
{
string type = GetNotNull (attrs, "type");
string assm = ExtractAssembly (ref type);
if (currentClientUrl == null || currentClientUrl == "")
throw new RemotingException ("url attribute is required in client element when it contains activated entries");
typeEntries.Add (new ActivatedClientTypeEntry (type, assm, currentClientUrl));
}
void ReadServiceActivated (SmallXmlParser.IAttrList attrs)
{
string type = GetNotNull (attrs, "type");
string assm = ExtractAssembly (ref type);
typeEntries.Add (new ActivatedServiceTypeEntry (type, assm));
}
void ReadClientWellKnown (SmallXmlParser.IAttrList attrs)
{
string url = GetNotNull (attrs, "url");
string type = GetNotNull (attrs, "type");
string assm = ExtractAssembly (ref type);
typeEntries.Add (new WellKnownClientTypeEntry (type, assm, url));
}
void ReadServiceWellKnown (SmallXmlParser.IAttrList attrs)
{
string objectUri = GetNotNull (attrs, "objectUri");
string smode = GetNotNull (attrs, "mode");
string type = GetNotNull (attrs, "type");
string assm = ExtractAssembly (ref type);
WellKnownObjectMode mode;
if (smode == "SingleCall") mode = WellKnownObjectMode.SingleCall;
else if (smode == "Singleton") mode = WellKnownObjectMode.Singleton;
else throw new RemotingException ("wellknown object mode '" + smode + "' is invalid");
typeEntries.Add (new WellKnownServiceTypeEntry (type, assm, objectUri, mode));
}
void ReadInteropXml (SmallXmlParser.IAttrList attrs, bool isElement)
{
Type t = Type.GetType (GetNotNull (attrs, "clr"));
string[] xmlName = GetNotNull (attrs, "xml").Split (',');
string localName = xmlName [0].Trim ();
string ns = xmlName.Length > 0 ? xmlName[1].Trim() : null;
if (isElement) SoapServices.RegisterInteropXmlElement (localName, ns, t);
else SoapServices.RegisterInteropXmlType (localName, ns, t);
}
void ReadPreload (SmallXmlParser.IAttrList attrs)
{
string type = attrs.GetValue ("type");
string assm = attrs.GetValue ("assembly");
if (type != null && assm != null)
throw new RemotingException ("Type and assembly attributes cannot be specified together");
if (type != null)
SoapServices.PreLoad (Type.GetType (type));
else if (assm != null)
SoapServices.PreLoad (Assembly.Load (assm));
else
throw new RemotingException ("Either type or assembly attributes must be specified");
}
string GetNotNull (SmallXmlParser.IAttrList attrs, string name)
{
string value = attrs.GetValue (name);
if (value == null || value == "")
throw new RemotingException (name + " attribute is required");
return value;
}
string ExtractAssembly (ref string type)
{
int i = type.IndexOf (',');
if (i == -1) return "";
string asm = type.Substring (i+1).Trim();
type = type.Substring (0, i).Trim();
return asm;
}
public void OnChars (string ch) {}
public void OnEndParsing (SmallXmlParser parser)
{
RemotingConfiguration.RegisterChannels (channelInstances, onlyDelayedChannels);
if (appName != null) RemotingConfiguration.ApplicationName = appName;
if (!onlyDelayedChannels)
RemotingConfiguration.RegisterTypes (typeEntries);
}
}
/*******************************************************************
* Internal data structures used by ConfigHandler, to store *
* machine.config's remoting related data. *
* If having them implemented this way, makes configuration too *
* slow, we can use string arrays. *
*******************************************************************/
internal class ChannelData {
internal string Ref;
internal string Type;
internal string Id;
internal string DelayLoadAsClientChannel;
ArrayList _serverProviders = new ArrayList ();
ArrayList _clientProviders = new ArrayList ();
Hashtable _customProperties = new Hashtable ();
internal ArrayList ServerProviders {
get {
if (_serverProviders == null) _serverProviders = new ArrayList ();
return _serverProviders;
}
}
public ArrayList ClientProviders {
get {
if (_clientProviders == null) _clientProviders = new ArrayList ();
return _clientProviders;
}
}
public Hashtable CustomProperties {
get {
if (_customProperties == null) _customProperties = new Hashtable ();
return _customProperties;
}
}
public void CopyFrom (ChannelData other)
{
if (Ref == null) Ref = other.Ref;
if (Id == null) Id = other.Id;
if (Type == null) Type = other.Type;
if (DelayLoadAsClientChannel == null) DelayLoadAsClientChannel = other.DelayLoadAsClientChannel;
if (other._customProperties != null)
{
foreach (DictionaryEntry entry in other._customProperties)
if (!CustomProperties.ContainsKey (entry.Key))
CustomProperties [entry.Key] = entry.Value;
}
if (_serverProviders == null && other._serverProviders != null)
{
foreach (ProviderData prov in other._serverProviders)
{
ProviderData np = new ProviderData();
np.CopyFrom (prov);
ServerProviders.Add (np);
}
}
if (_clientProviders == null && other._clientProviders != null)
{
foreach (ProviderData prov in other._clientProviders)
{
ProviderData np = new ProviderData();
np.CopyFrom (prov);
ClientProviders.Add (np);
}
}
}
}
internal class ProviderData {
internal string Ref;
internal string Type;
internal string Id;
internal Hashtable CustomProperties = new Hashtable ();
internal IList CustomData;
public void CopyFrom (ProviderData other)
{
if (Ref == null) Ref = other.Ref;
if (Id == null) Id = other.Id;
if (Type == null) Type = other.Type;
foreach (DictionaryEntry entry in other.CustomProperties)
if (!CustomProperties.ContainsKey (entry.Key))
CustomProperties [entry.Key] = entry.Value;
if (other.CustomData != null)
{
if (CustomData == null) CustomData = new ArrayList ();
foreach (SinkProviderData data in other.CustomData)
CustomData.Add (data);
}
}
}
internal class FormatterData: ProviderData {
}
}
|