536cd135cc
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
646 lines
25 KiB
C#
646 lines
25 KiB
C#
//-----------------------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
namespace System.ServiceModel.Configuration
|
|
{
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Configuration;
|
|
using System.Diagnostics;
|
|
using System.Runtime;
|
|
using System.Runtime.Diagnostics;
|
|
using System.Security;
|
|
using System.ServiceModel;
|
|
using System.ServiceModel.Diagnostics;
|
|
using System.Xml;
|
|
|
|
public abstract class ServiceModelExtensionCollectionElement<TServiceModelExtensionElement> : ConfigurationElement, ICollection<TServiceModelExtensionElement>, IConfigurationContextProviderInternal
|
|
where TServiceModelExtensionElement : ServiceModelExtensionElement
|
|
{
|
|
[Fx.Tag.SecurityNote(Critical = "Stores information used in a security decision.")]
|
|
[SecurityCritical]
|
|
EvaluationContextHelper contextHelper;
|
|
|
|
string extensionCollectionName = null;
|
|
bool modified = false;
|
|
List<TServiceModelExtensionElement> items = null;
|
|
ConfigurationPropertyCollection properties = null;
|
|
|
|
internal ServiceModelExtensionCollectionElement(string extensionCollectionName)
|
|
{
|
|
this.extensionCollectionName = extensionCollectionName;
|
|
}
|
|
|
|
public TServiceModelExtensionElement this[int index]
|
|
{
|
|
get { return this.Items[index]; }
|
|
}
|
|
|
|
public TServiceModelExtensionElement this[Type extensionType]
|
|
{
|
|
get
|
|
{
|
|
if (extensionType == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("extensionType");
|
|
}
|
|
|
|
if (!this.CollectionElementBaseType.IsAssignableFrom(extensionType))
|
|
{
|
|
#pragma warning disable 56506 //Microsoft; Variable 'extensionType' checked for null previously
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("extensionType",
|
|
SR.GetString(SR.ConfigInvalidExtensionType,
|
|
extensionType.ToString(),
|
|
this.CollectionElementBaseType.FullName,
|
|
this.extensionCollectionName));
|
|
#pragma warning restore
|
|
}
|
|
TServiceModelExtensionElement retval = null;
|
|
|
|
foreach (TServiceModelExtensionElement collectionElement in this)
|
|
{
|
|
if (null != collectionElement)
|
|
{
|
|
if (collectionElement.GetType() == extensionType)
|
|
{
|
|
retval = collectionElement;
|
|
}
|
|
}
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
}
|
|
|
|
public int Count
|
|
{
|
|
get { return this.Items.Count; }
|
|
}
|
|
|
|
bool ICollection<TServiceModelExtensionElement>.IsReadOnly
|
|
{
|
|
get { return this.IsReadOnly(); }
|
|
}
|
|
|
|
internal List<TServiceModelExtensionElement> Items
|
|
{
|
|
get
|
|
{
|
|
if (this.items == null)
|
|
{
|
|
this.items = new List<TServiceModelExtensionElement>();
|
|
}
|
|
return this.items;
|
|
}
|
|
}
|
|
|
|
protected override ConfigurationPropertyCollection Properties
|
|
{
|
|
get
|
|
{
|
|
if (this.properties == null)
|
|
{
|
|
this.properties = new ConfigurationPropertyCollection();
|
|
}
|
|
return this.properties;
|
|
}
|
|
}
|
|
|
|
public virtual void Add(TServiceModelExtensionElement element)
|
|
{
|
|
if (this.IsReadOnly())
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(SR.GetString(SR.ConfigReadOnly)));
|
|
}
|
|
if (element == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
|
|
}
|
|
|
|
element.ExtensionCollectionName = this.extensionCollectionName;
|
|
|
|
if (this.Contains(element))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("element", SR.GetString(SR.ConfigDuplicateKey, element.ConfigurationElementName));
|
|
}
|
|
else if (!this.CanAdd(element))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("element",
|
|
SR.GetString(SR.ConfigElementTypeNotAllowed,
|
|
element.ConfigurationElementName,
|
|
this.extensionCollectionName));
|
|
}
|
|
else
|
|
{
|
|
element.ContainingEvaluationContext = ConfigurationHelpers.GetEvaluationContext(this);
|
|
ConfigurationProperty configProperty = new ConfigurationProperty(element.ConfigurationElementName, element.GetType(), null);
|
|
this.Properties.Add(configProperty);
|
|
this[configProperty] = element;
|
|
this.Items.Add(element);
|
|
this.modified = true;
|
|
}
|
|
}
|
|
|
|
internal void AddItem(TServiceModelExtensionElement element)
|
|
{
|
|
if (this.IsReadOnly())
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(SR.GetString(SR.ConfigReadOnly)));
|
|
}
|
|
element.ExtensionCollectionName = this.extensionCollectionName;
|
|
element.ContainingEvaluationContext = ConfigurationHelpers.GetEvaluationContext(this);
|
|
this.Items.Add(element);
|
|
this.modified = true;
|
|
}
|
|
|
|
public virtual bool CanAdd(TServiceModelExtensionElement element)
|
|
{
|
|
if (null == element)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
|
|
}
|
|
|
|
bool retval = false;
|
|
Type elementType = element.GetType();
|
|
|
|
if (!this.IsReadOnly())
|
|
{
|
|
if (!this.ContainsKey(elementType))
|
|
{
|
|
retval = element.CanAdd(this.extensionCollectionName, ConfigurationHelpers.GetEvaluationContext(this));
|
|
}
|
|
else if (DiagnosticUtility.ShouldTraceWarning)
|
|
{
|
|
TraceUtility.TraceEvent(TraceEventType.Warning,
|
|
TraceCode.ExtensionElementAlreadyExistsInCollection,
|
|
SR.GetString(SR.TraceCodeExtensionElementAlreadyExistsInCollection),
|
|
this.CreateCanAddRecord(this[elementType]), this, null);
|
|
}
|
|
}
|
|
else if (DiagnosticUtility.ShouldTraceWarning)
|
|
{
|
|
TraceUtility.TraceEvent(TraceEventType.Warning,
|
|
TraceCode.ConfigurationIsReadOnly,
|
|
SR.GetString(SR.TraceCodeConfigurationIsReadOnly),
|
|
null, this, null);
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
DictionaryTraceRecord CreateCanAddRecord(TServiceModelExtensionElement element)
|
|
{
|
|
return this.CreateCanAddRecord(element, new Dictionary<string, string>(3));
|
|
}
|
|
|
|
DictionaryTraceRecord CreateCanAddRecord(TServiceModelExtensionElement element, Dictionary<string, string> values)
|
|
{
|
|
values["ElementType"] = System.Runtime.Diagnostics.DiagnosticTraceBase.XmlEncode(typeof(TServiceModelExtensionElement).AssemblyQualifiedName);
|
|
values["ConfiguredSectionName"] = element.ConfigurationElementName;
|
|
values["CollectionName"] = ConfigurationStrings.ExtensionsSectionPath + "/" + this.extensionCollectionName;
|
|
return new DictionaryTraceRecord(values);
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
if (this.IsReadOnly())
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(SR.GetString(SR.ConfigReadOnly)));
|
|
}
|
|
if (this.Properties.Count > 0)
|
|
{
|
|
this.modified = true;
|
|
}
|
|
|
|
List<string> propertiesToRemove = new List<string>(this.Items.Count);
|
|
foreach (TServiceModelExtensionElement item in this.Items)
|
|
{
|
|
propertiesToRemove.Add(item.ConfigurationElementName);
|
|
}
|
|
|
|
this.Items.Clear();
|
|
|
|
foreach (string name in propertiesToRemove)
|
|
{
|
|
this.Properties.Remove(name);
|
|
}
|
|
}
|
|
|
|
internal Type CollectionElementBaseType
|
|
{
|
|
get { return typeof(TServiceModelExtensionElement); }
|
|
}
|
|
|
|
public bool Contains(TServiceModelExtensionElement element)
|
|
{
|
|
if (element == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
|
|
}
|
|
return this.ContainsKey(element.GetType());
|
|
}
|
|
|
|
public bool ContainsKey(Type elementType)
|
|
{
|
|
if (elementType == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("elementType");
|
|
}
|
|
return (this[elementType] != null);
|
|
}
|
|
|
|
public bool ContainsKey(string elementName)
|
|
{
|
|
if (string.IsNullOrEmpty(elementName))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("elementName");
|
|
}
|
|
bool retval = false;
|
|
foreach (TServiceModelExtensionElement element in this)
|
|
{
|
|
if (null != element)
|
|
{
|
|
string configuredSectionName = element.ConfigurationElementName;
|
|
if (configuredSectionName.Equals(elementName, StringComparison.Ordinal))
|
|
{
|
|
retval = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
public void CopyTo(TServiceModelExtensionElement[] elements, int start)
|
|
{
|
|
if (elements == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("elements");
|
|
}
|
|
if (start < 0 || start >= elements.Length)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("start",
|
|
SR.GetString(SR.ConfigInvalidStartValue,
|
|
elements.Length - 1,
|
|
start));
|
|
}
|
|
|
|
foreach (TServiceModelExtensionElement element in this)
|
|
{
|
|
if (null != element)
|
|
{
|
|
string configuredSectionName = element.ConfigurationElementName;
|
|
|
|
TServiceModelExtensionElement copiedElement = this.CreateNewSection(configuredSectionName);
|
|
if ((copiedElement != null) && (start < elements.Length))
|
|
{
|
|
copiedElement.CopyFrom(element);
|
|
elements[start] = copiedElement;
|
|
++start;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the extension element, or null if the type cannot be loaded in certain situations (see the code for details).
|
|
/// </summary>
|
|
TServiceModelExtensionElement CreateNewSection(string name)
|
|
{
|
|
if (this.ContainsKey(name) && !(name == ConfigurationStrings.Clear || name == ConfigurationStrings.Remove))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(SR.GetString(SR.ConfigDuplicateItem,
|
|
name,
|
|
this.GetType().Name),
|
|
this.ElementInformation.Source,
|
|
this.ElementInformation.LineNumber));
|
|
}
|
|
|
|
TServiceModelExtensionElement retval = null;
|
|
|
|
Type elementType;
|
|
ContextInformation evaluationContext = ConfigurationHelpers.GetEvaluationContext(this);
|
|
try
|
|
{
|
|
elementType = GetExtensionType(evaluationContext, name);
|
|
}
|
|
catch (ConfigurationErrorsException e)
|
|
{
|
|
// Work-around for bug 219506@CSDMain: if the extension type cannot be loaded, we'll ignore
|
|
// the exception when running in win8 app container and reading from machine.config.
|
|
if (System.ServiceModel.Channels.AppContainerInfo.IsRunningInAppContainer && evaluationContext.IsMachineLevel)
|
|
{
|
|
DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
|
|
if (null != elementType)
|
|
{
|
|
if (this.CollectionElementBaseType.IsAssignableFrom(elementType))
|
|
{
|
|
retval = (TServiceModelExtensionElement)Activator.CreateInstance(elementType);
|
|
retval.ExtensionCollectionName = this.extensionCollectionName;
|
|
retval.ConfigurationElementName = name;
|
|
retval.InternalInitializeDefault();
|
|
}
|
|
else
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(SR.GetString(SR.ConfigInvalidExtensionElement,
|
|
name,
|
|
this.CollectionElementBaseType.FullName),
|
|
this.ElementInformation.Source,
|
|
this.ElementInformation.LineNumber));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(SR.GetString(SR.ConfigInvalidExtensionElementName,
|
|
name,
|
|
this.extensionCollectionName),
|
|
this.ElementInformation.Source,
|
|
this.ElementInformation.LineNumber));
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
[Fx.Tag.SecurityNote(Critical = "Calls SecurityCritical method UnsafeLookupCollection which elevates in order to load config.",
|
|
Safe = "Does not leak any config objects.")]
|
|
[SecuritySafeCritical]
|
|
Type GetExtensionType(ContextInformation evaluationContext, string name)
|
|
{
|
|
ExtensionElementCollection collection = ExtensionsSection.UnsafeLookupCollection(this.extensionCollectionName, evaluationContext);
|
|
if (collection.ContainsKey(name))
|
|
{
|
|
ExtensionElement element = collection[name];
|
|
Type elementType = Type.GetType(element.Type, false);
|
|
if (null == elementType)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(SR.GetString(SR.ConfigInvalidType, element.Type, element.Name),
|
|
this.ElementInformation.Source,
|
|
this.ElementInformation.LineNumber));
|
|
}
|
|
return elementType;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
internal void MergeWith(List<TServiceModelExtensionElement> parentExtensionElements)
|
|
{
|
|
ServiceModelExtensionCollectionElement<TServiceModelExtensionElement>.Merge(parentExtensionElements, this);
|
|
this.Clear();
|
|
foreach (TServiceModelExtensionElement parentExtensionElement in parentExtensionElements)
|
|
{
|
|
this.Add(parentExtensionElement);
|
|
}
|
|
}
|
|
|
|
static void Merge(List<TServiceModelExtensionElement> parentExtensionElements, IEnumerable<TServiceModelExtensionElement> childExtensionElements)
|
|
{
|
|
foreach (TServiceModelExtensionElement childExtensionElement in childExtensionElements)
|
|
{
|
|
if (childExtensionElement is ClearBehaviorElement)
|
|
{
|
|
parentExtensionElements.Clear();
|
|
}
|
|
else if (childExtensionElement is RemoveBehaviorElement)
|
|
{
|
|
string childExtensionElementName = (childExtensionElement as RemoveBehaviorElement).Name;
|
|
if (!string.IsNullOrEmpty(childExtensionElementName))
|
|
{
|
|
parentExtensionElements.RemoveAll(element => element != null && element.ConfigurationElementName == childExtensionElementName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Type childExtensionElementType = childExtensionElement.GetType();
|
|
parentExtensionElements.RemoveAll(element => element != null && element.GetType() == childExtensionElementType);
|
|
parentExtensionElements.Add(childExtensionElement);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fx.Tag.SecurityNote(Critical = "Uses the critical helper SetIsPresent.",
|
|
Safe = "Controls how/when SetIsPresent is used, not arbitrarily callable from PT (method is protected and class is sealed).")]
|
|
[SecuritySafeCritical]
|
|
protected override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
|
|
{
|
|
SetIsPresent();
|
|
DeserializeElementCore(reader);
|
|
}
|
|
|
|
private void DeserializeElementCore(XmlReader reader)
|
|
{
|
|
if (reader.HasAttributes && 0 < reader.AttributeCount)
|
|
{
|
|
while (reader.MoveToNextAttribute())
|
|
{
|
|
if (this.Properties.Contains(reader.Name))
|
|
{
|
|
this[reader.Name] = this.Properties[reader.Name].Converter.ConvertFromString(reader.Value);
|
|
}
|
|
else
|
|
{
|
|
this.OnDeserializeUnrecognizedAttribute(reader.Name, reader.Value);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (XmlNodeType.Element != reader.NodeType)
|
|
{
|
|
reader.MoveToElement();
|
|
}
|
|
|
|
XmlReader subTree = reader.ReadSubtree();
|
|
if (subTree.Read())
|
|
{
|
|
while (subTree.Read())
|
|
{
|
|
if (XmlNodeType.Element == subTree.NodeType)
|
|
{
|
|
// Create new child element and add it to the property collection to
|
|
// associate the element with an EvaluationContext. Then deserialize
|
|
// XML further to set actual values.
|
|
TServiceModelExtensionElement collectionElement = this.CreateNewSection(subTree.Name);
|
|
if (collectionElement != null)
|
|
{
|
|
this.Add(collectionElement);
|
|
collectionElement.DeserializeInternal(subTree, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fx.Tag.SecurityNote(Critical = "Calls ConfigurationHelpers.SetIsPresent which elevates in order to set a property.")]
|
|
[SecurityCritical]
|
|
void SetIsPresent()
|
|
{
|
|
ConfigurationHelpers.SetIsPresent(this);
|
|
}
|
|
|
|
public System.Collections.Generic.IEnumerator<TServiceModelExtensionElement> GetEnumerator()
|
|
{
|
|
for (int index = 0; index < this.Items.Count; ++index)
|
|
{
|
|
TServiceModelExtensionElement currentValue = items[index];
|
|
yield return currentValue;
|
|
}
|
|
}
|
|
|
|
protected override bool IsModified()
|
|
{
|
|
bool retval = this.modified;
|
|
if (!retval)
|
|
{
|
|
for (int i = 0; i < this.Items.Count; i++)
|
|
{
|
|
TServiceModelExtensionElement element = this.Items[i];
|
|
if (element.IsModifiedInternal())
|
|
{
|
|
retval = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
protected override bool OnDeserializeUnrecognizedElement(string elementName, XmlReader reader)
|
|
{
|
|
// When this is used as a DefaultCollection (i.e. CommonBehaviors)
|
|
// the element names are unrecognized by the parent tag, which delegates
|
|
// to the collection's OnDeserializeUnrecognizedElement. In this case,
|
|
// an unrecognized element may be expected, simply try to deserialize the
|
|
// element and let DeserializeElement() throw the appropriate exception if
|
|
// an error is hit.
|
|
this.DeserializeElement(reader, false);
|
|
return true;
|
|
}
|
|
|
|
public bool Remove(TServiceModelExtensionElement element)
|
|
{
|
|
if (element == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
|
|
}
|
|
bool retval = false;
|
|
if (this.Contains(element))
|
|
{
|
|
string configuredSectionName = element.ConfigurationElementName;
|
|
|
|
TServiceModelExtensionElement existingElement = (TServiceModelExtensionElement)this[element.GetType()];
|
|
this.Items.Remove(existingElement);
|
|
this.Properties.Remove(configuredSectionName);
|
|
this.modified = true;
|
|
retval = true;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
[Fx.Tag.SecurityNote(Critical = "Accesses critical field contextHelper.")]
|
|
[SecurityCritical]
|
|
protected override void Reset(ConfigurationElement parentElement)
|
|
{
|
|
ServiceModelExtensionCollectionElement<TServiceModelExtensionElement> collection =
|
|
(ServiceModelExtensionCollectionElement<TServiceModelExtensionElement>)parentElement;
|
|
foreach (TServiceModelExtensionElement collectionElement in collection.Items)
|
|
{
|
|
this.Items.Add(collectionElement);
|
|
}
|
|
// Update my properties
|
|
this.UpdateProperties(collection);
|
|
|
|
this.contextHelper.OnReset(parentElement);
|
|
|
|
base.Reset(parentElement);
|
|
}
|
|
|
|
protected override void ResetModified()
|
|
{
|
|
for (int i = 0; i < this.Items.Count; i++)
|
|
{
|
|
TServiceModelExtensionElement collectionElement = this.Items[i];
|
|
collectionElement.ResetModifiedInternal();
|
|
}
|
|
this.modified = false;
|
|
}
|
|
|
|
protected void SetIsModified()
|
|
{
|
|
this.modified = true;
|
|
}
|
|
|
|
protected override void SetReadOnly()
|
|
{
|
|
base.SetReadOnly();
|
|
|
|
for (int i = 0; i < this.Items.Count; i++)
|
|
{
|
|
TServiceModelExtensionElement element = this.Items[i];
|
|
element.SetReadOnlyInternal();
|
|
}
|
|
}
|
|
|
|
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
|
{
|
|
return this.GetEnumerator();
|
|
}
|
|
|
|
protected override void Unmerge(ConfigurationElement sourceElement, ConfigurationElement parentElement, ConfigurationSaveMode saveMode)
|
|
{
|
|
if (sourceElement == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ServiceModelExtensionCollectionElement<TServiceModelExtensionElement> sourceCollectionElement = (ServiceModelExtensionCollectionElement<TServiceModelExtensionElement>)sourceElement;
|
|
|
|
this.UpdateProperties(sourceCollectionElement);
|
|
base.Unmerge(sourceElement, parentElement, saveMode);
|
|
}
|
|
|
|
void UpdateProperties(ServiceModelExtensionCollectionElement<TServiceModelExtensionElement> sourceElement)
|
|
{
|
|
foreach (ConfigurationProperty property in sourceElement.Properties)
|
|
{
|
|
if (!this.Properties.Contains(property.Name))
|
|
{
|
|
this.Properties.Add(property);
|
|
}
|
|
}
|
|
foreach (TServiceModelExtensionElement extension in this.Items)
|
|
{
|
|
if (extension is ClearBehaviorElement || extension is RemoveBehaviorElement)
|
|
continue;
|
|
|
|
string configuredSectionName = extension.ConfigurationElementName;
|
|
if (!this.Properties.Contains(configuredSectionName))
|
|
{
|
|
ConfigurationProperty configProperty = new ConfigurationProperty(configuredSectionName, extension.GetType(), null);
|
|
this.Properties.Add(configProperty);
|
|
}
|
|
}
|
|
}
|
|
|
|
ContextInformation IConfigurationContextProviderInternal.GetEvaluationContext()
|
|
{
|
|
return this.EvaluationContext;
|
|
}
|
|
|
|
[Fx.Tag.SecurityNote(Critical = "Accesses critical field contextHelper.",
|
|
Miscellaneous = "RequiresReview -- the return value will be used for a security decision -- see comment in interface definition.")]
|
|
[SecurityCritical]
|
|
ContextInformation IConfigurationContextProviderInternal.GetOriginalEvaluationContext()
|
|
{
|
|
return this.contextHelper.GetOriginalContext(this);
|
|
}
|
|
}
|
|
}
|
|
|