Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Framework / System / Windows / Markup / XAMLParseException.cs / 1 / XAMLParseException.cs
//----------------------------------------------------------------------------
//
// File: XamlParseException.cs
//
// Description:
// Parser exceptions
//
//
// History:
// 6/06/01: rogerg Created
// 5/28/03: peterost Ported to wcp
//
// Copyright (C) 2003 by Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Xml;
using System.IO;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Text;
using System.Globalization;
using System.ComponentModel;
using System.Security;
using System.Runtime.Serialization;
using System.Security.Permissions;
using MS.Utility;
using MS.Internal;
#if PBTCOMPILER
namespace MS.Internal.Markup
#else
using System.Windows;
using System.Windows.Threading;
namespace System.Windows.Markup
#endif
{
///Exception class for parser specific exceptions
[Serializable]
#if PBTCOMPILER
internal class XamlParseException : SystemException
#else
public class XamlParseException : SystemException
#endif
{
#region Public
#region Constructors
///
/// Constructor
///
public XamlParseException() : base ()
{
}
///
/// Constructor
///
///
/// Exception message
///
public XamlParseException(string message) : base (message)
{
}
///
/// Constructor
///
/// Exception message
/// exception occured
public XamlParseException(string message, Exception innerException) : base(message, innerException)
{
}
///
/// Constructor
///
///
/// Exception message
///
///
/// lineNumber the exception occured at
///
///
/// LinePosition the Exception occured at.
///
///
public XamlParseException(string message,int lineNumber, int linePosition) : this (message)
{
_lineNumber = lineNumber;
_linePosition = linePosition;
}
///
/// Constructor
///
///
/// Exception message
///
///
/// lineNumber the exception occured at
///
///
/// LinePosition the Exception occured at.
///
///
/// original Exception that was thrown.
///
public XamlParseException(string message,int lineNumber, int linePosition,Exception innerException)
: this(message, innerException)
{
_lineNumber = lineNumber;
_linePosition = linePosition;
}
#endregion Constructors
#region Properties
///
/// LineNumber that the exception occured on.
///
public int LineNumber
{
get { return _lineNumber; }
}
///
/// LinePosition that the exception occured on.
///
public int LinePosition
{
get { return _linePosition; }
}
///
/// If this is set, it indicates that the Xaml exception occurred
/// in the context of a dictionary item, and this was the Xaml Key
/// value of that item.
///
public object KeyContext
{
#if PBTCOMPILER
set { _keyContext= value; }
#else
get { return _keyContext; }
internal set { _keyContext= value; }
#endif
}
///
/// If this is set, it indicates that the Xaml exception occurred
/// in the context of an object with a Xaml Uid set, and this was the
/// value of that Uid.
///
public string UidContext
{
#if PBTCOMPILER
set { _uidContext = value; }
#else
get { return _uidContext; }
internal set { _uidContext = value; }
#endif
}
///
/// If this is set, it indicates that the Xaml exception occurred
/// in the context of an object with a Xaml Name set, and this was the
/// value of that name.
///
public string NameContext
{
#if PBTCOMPILER
set { _nameContext = value; }
#else
get { return _nameContext; }
internal set { _nameContext = value; }
#endif
}
///
/// The BaseUri in effect at the point of the exception.
///
public Uri BaseUri
{
#if PBTCOMPILER
set { _baseUri = value; }
#else
get { return _baseUri; }
internal set { _baseUri = value; }
#endif
}
#endregion Properties
#endregion Public
#region Private
#region Serialization
///
/// Internal constructor used for serialization when marshalling an
/// exception of this type across and AppDomain or machine boundary.
///
///
/// Contains all the information needed to serialize or deserialize
/// the object.
///
///
/// Describes the source and destination of a given serialized stream,
/// as well as a means for serialization to retain that context and an
/// additional caller-defined context.
///
//CASRemoval:[SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter=true)]
protected XamlParseException(
SerializationInfo info,
StreamingContext context
)
: base(info, context)
{
_lineNumber = info.GetInt32("Line");
_linePosition = info.GetInt32("Position");
}
///
/// Populates a SerializationInfo with the data needed to serialize the target object.
///
///
/// The SerializationInfo to populate with data.
///
///
/// The destination for this serialization.
///
///
///
/// Critical: calls Exception.GetObjectData which LinkDemands
/// TreatAsSafe: We make the corresponding demand here, to ensure that it becomes a full
/// demand.
///
[SecurityCritical, SecurityTreatAsSafe]
#if ! PBTCOMPILER
[SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.SerializationFormatter)]
#else
[SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter=true)]
#endif
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("Line", (Int32)_lineNumber);
info.AddValue("Position", (Int32)_linePosition);
}
#endregion Serialization
#region internal helper methods
#if ! PBTCOMPILER
//
// Return the relative file path for current markup stream or file.
// If the stream comes from assembly resource with .baml extension, this method
// still reports .xaml.
// The purpose of this method is to help developer to debug a failed baml stream.
//
internal static string GetMarkupFilePath(Uri resourceUri)
{
string bamlFilePath = string.Empty;
string xamlFilePath = string.Empty;
if (resourceUri != null)
{
if (resourceUri.IsAbsoluteUri)
{
bamlFilePath = resourceUri.GetComponents(UriComponents.Path, UriFormat.Unescaped);
}
else
{
bamlFilePath = resourceUri.OriginalString;
}
// Replace the .baml with .xaml file extension.
xamlFilePath = bamlFilePath.Replace(BamlExt, XamlExt);
// Confirm the result has a .xaml file extension.
if (-1 == xamlFilePath.LastIndexOf(XamlExt, StringComparison.Ordinal))
xamlFilePath = string.Empty;
}
return xamlFilePath;
}
//
// Get context information at the point of the exception, such as
// names and Uids.
//
internal static void GetObjectContext(
BamlRecordReader bamlRecordReader,
XamlObjectIds currentXamlObjectIds,
XamlObjectIds contextXamlObjectIds,
out Type objectType)
{
object parentObject = null;
GetObjectContext( bamlRecordReader, currentXamlObjectIds, contextXamlObjectIds, out objectType,
out parentObject );
}
internal static void GetObjectContext(
BamlRecordReader bamlRecordReader,
out object parentObject )
{
XamlObjectIds currentXamlObjectIds = new XamlObjectIds();
Type objectType;
GetObjectContext( bamlRecordReader, currentXamlObjectIds, null, out objectType, out parentObject );
}
internal static void GetObjectContext(
BamlRecordReader bamlRecordReader,
XamlObjectIds currentXamlObjectIds,
XamlObjectIds contextXamlObjectIds,
out Type objectType,
out object parentObject)
{
ParserStack contextStack;
ReaderContextStackData readerContextStackData;
parentObject = null;
objectType = null;
// We get context from the reader, so there's nothing to do if we don't
// have one.
if (bamlRecordReader == null)
{
return;
}
contextStack = bamlRecordReader.ContextStack;
if( contextStack.Count == 0 )
{
return;
}
// Walk the reader's context stack and look for context information
// (x:Name, x:Key, and x:Uid).
bool currentObjectElementFound = (currentXamlObjectIds == null); // (See below for usage and comment)
bool parentObjectElementFound = false;
for( int i = contextStack.Count-1; i >= 0; i-- )
{
readerContextStackData = contextStack[i] as ReaderContextStackData;
// First, see if we can fill in the currentXamlObjectIds.
//
// The context stack data has entries for both objects and properties
// E.g. if we're trying to parse "Foo" under >>,
// the CurrentContext will be a property record for the property element
// Button.Background. So the actual current object element will be Button.
// So we check here to find the first object element as we're walking up
// the stack. (Note that we also ignore elements that were injected
// by the parser, and objects that are placeholders.)
if( (!currentObjectElementFound || !parentObjectElementFound )
&&
readerContextStackData.IsObjectElement
&&
(readerContextStackData.ContextFlags & ReaderFlags.CollectionHolder) == 0
&&
(readerContextStackData.ContextFlags & ReaderFlags.InjectedElement) == 0 )
{
if( !currentObjectElementFound )
{
currentObjectElementFound = true;
// Get any/all Ids of the current object element.
currentXamlObjectIds.Name = readerContextStackData.ElementNameOrPropertyName;
currentXamlObjectIds.Uid = readerContextStackData.Uid;
currentXamlObjectIds.Key = readerContextStackData.Key;
// Determine the type of the current object element.
object currentObject = readerContextStackData.ObjectData;
if (currentObject != null)
{
// If this is a FEF, use the FEF's type
if (currentObject is FrameworkElementFactory)
{
objectType = ((FrameworkElementFactory)currentObject).Type;
}
else
{
objectType = currentObject.GetType();
}
}
}
else
{
parentObjectElementFound = true;
parentObject = readerContextStackData.ObjectData;
}
}
// Second, look at all entries in the stack, in search of the nearest
// Ids.
if( contextXamlObjectIds != null )
{
if( contextXamlObjectIds.Name == null && readerContextStackData.ElementNameOrPropertyName != null )
{
contextXamlObjectIds.Name = readerContextStackData.ElementNameOrPropertyName;
}
if( contextXamlObjectIds.Uid == null && readerContextStackData.Uid != null )
{
contextXamlObjectIds.Uid = readerContextStackData.Uid;
}
if( contextXamlObjectIds.Key == null && readerContextStackData.Key != null )
{
contextXamlObjectIds.Key = readerContextStackData.Key;
}
}
}
return;
}
[Flags]
private enum ContextBits { Type=1, File=2, Line=4 };
//
// Apply the context to the original error message.
// The context contains :
// Current markup file
// Current element name in the markup file.
//
internal static string GenerateErrorMessageContext(
int lineNumber,
int linePosition,
Uri baseUri,
XamlObjectIds xamlObjectIds,
Type objectType)
{
string message=" ";
string xamlFile = GetMarkupFilePath(baseUri);
string simpleObjectId = null;
// Calculate the simpleObjectId. Use the object's name, key, Uid, or
// type name, whichever is available (in that order).
if( xamlObjectIds != null )
{
if( xamlObjectIds.Name != null )
{
simpleObjectId = xamlObjectIds.Name;
}
else if( xamlObjectIds.Key != null )
{
simpleObjectId = xamlObjectIds.Key.ToString();
}
else if( xamlObjectIds.Uid != null )
{
simpleObjectId = xamlObjectIds.Uid;
}
}
if( simpleObjectId == null && objectType != null )
{
simpleObjectId = objectType.ToString();
}
ContextBits flags = 0;
if (simpleObjectId != null)
flags |= ContextBits.Type;
if (!String.IsNullOrEmpty(xamlFile))
flags |= ContextBits.File;
if (lineNumber > 0 )
flags |= ContextBits.Line;
switch(flags)
{
case 0:
message = String.Empty;
break;
case ContextBits.Type:
message = SR.Get(SRID.ParserErrorContext_Type, simpleObjectId);
break;
case ContextBits.File:
message = SR.Get(SRID.ParserErrorContext_File, xamlFile);
break;
case ContextBits.Type | ContextBits.File:
message = SR.Get(SRID.ParserErrorContext_Type_File, simpleObjectId, xamlFile);
break;
case ContextBits.Line:
message = SR.Get(SRID.ParserErrorContext_Line, lineNumber, linePosition);
break;
case ContextBits.Type | ContextBits.Line:
message = SR.Get(SRID.ParserErrorContext_Type_Line, simpleObjectId, lineNumber, linePosition);
break;
case ContextBits.File | ContextBits.Line:
message = SR.Get(SRID.ParserErrorContext_File_Line, xamlFile, lineNumber, linePosition);
break;
case ContextBits.Type | ContextBits.File | ContextBits.Line:
message = SR.Get(SRID.ParserErrorContext_Type_File_Line, simpleObjectId, xamlFile, lineNumber, linePosition);
break;
}
return message;
}
#endif
//
// This method creates a XamlParseException and throws it. If provided, it incorporates
// the information such as baseUri and elementName into the exception, possibly in the exception
// message, and always in the XamlParseException itself. When an inner exception is provided,
// we incorporate its Message into the XamlParseException's message.
//
// When an exception is thrown during xaml load (compile), we simply identify its location with
// the line number and position. When an exception is thrown at runtime (baml load),
// we identify its location with as much information as we can, since we don't have line numbers
// available. So the following identifying information is provided, if available: BaseUri,
// nearest x:Uid in context, nearest x:Name, and nearest x:Key.
//
internal static void ThrowException(
string message,
Exception innerException,
int lineNumber,
int linePosition,
Uri baseUri,
XamlObjectIds currentXamlObjectIds,
XamlObjectIds contextXamlObjectIds,
Type objectType
)
{
// If there's an inner exception, we'll append its message to our own.
if( innerException != null && innerException.Message != null )
{
StringBuilder sb = new StringBuilder(message);
if( innerException.Message != String.Empty )
{
sb.Append( " " );
}
sb.Append( innerException.Message );
message = sb.ToString();
}
// If we have line numbers, then we are
// parsing a xaml file where the line number has been explicitly set, so
// throw a xaml exception. Otherwise we are parsing a baml file, or we
// don't know what the line number is.
XamlParseException xamlParseException;
#if !PBTCOMPILER
string contextMessage = XamlParseException.GenerateErrorMessageContext(
lineNumber,
linePosition,
baseUri,
currentXamlObjectIds,
objectType);
message = message + " " + contextMessage;
#endif
// If the exception was a XamlParse exception on the other
// side of a Reflection Invoke, then just pull up the Parse exception.
if (innerException is TargetInvocationException && innerException.InnerException is XamlParseException)
{
xamlParseException = (XamlParseException)innerException.InnerException;
}
else
{
if (lineNumber > 0 )
{
xamlParseException = new XamlParseException(message, lineNumber, linePosition, innerException);
}
else
{
#if PBTCOMPILER
throw new InvalidOperationException(message);
#else
xamlParseException = new XamlParseException(message, innerException);
#endif
}
}
// Fill in the exception with some more runtime-context information.
if (contextXamlObjectIds != null)
{
xamlParseException.NameContext = contextXamlObjectIds.Name;
xamlParseException.UidContext = contextXamlObjectIds.Uid;
xamlParseException.KeyContext = contextXamlObjectIds.Key;
}
xamlParseException.BaseUri = baseUri;
#if !PBTCOMPILER
if( TraceMarkup.IsEnabled )
{
TraceMarkup.TraceActivityItem( TraceMarkup.ThrowException,
xamlParseException );
}
#endif
throw xamlParseException;
}
//
// Runtime (baml loader) ThrowException wrapper that takes an inner exception and
// incorporates context from the ParserContext.
//
#if !PBTCOMPILER
internal static void ThrowException(ParserContext parserContext, int lineNumber, int linePosition, string message, Exception innerException)
{
if( parserContext != null )
{
Type objectType;
XamlObjectIds currentXamlObjectIds = new XamlObjectIds();
XamlObjectIds contextXamlObjectIds = new XamlObjectIds();
GetObjectContext(
parserContext.BamlReader,
currentXamlObjectIds,
contextXamlObjectIds,
out objectType );
ThrowException(
message,
innerException,
lineNumber,
linePosition,
parserContext.BaseUri,
currentXamlObjectIds,
contextXamlObjectIds,
objectType );
}
else
{
ThrowException(
message,
innerException,
lineNumber,
linePosition );
}
}
#endif
//
// Convenience ThrowException wrapper that just takes the message, inner exception, and line number.
//
internal static void ThrowException(
string message,
Exception innerException,
int lineNumber,
int linePosition )
{
ThrowException( message, innerException, lineNumber, linePosition,
null, null, null, null );
}
#endregion internal helper methods
#region const
internal const string BamlExt = ".baml";
internal const string XamlExt = ".xaml";
#endregion const
#region Data
int _lineNumber = 0;
int _linePosition = 0;
object _keyContext = null;
string _uidContext = null;
string _nameContext = null;
Uri _baseUri = null;
#endregion Data
#endregion Private
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
//
// File: XamlParseException.cs
//
// Description:
// Parser exceptions
//
//
// History:
// 6/06/01: rogerg Created
// 5/28/03: peterost Ported to wcp
//
// Copyright (C) 2003 by Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Xml;
using System.IO;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Text;
using System.Globalization;
using System.ComponentModel;
using System.Security;
using System.Runtime.Serialization;
using System.Security.Permissions;
using MS.Utility;
using MS.Internal;
#if PBTCOMPILER
namespace MS.Internal.Markup
#else
using System.Windows;
using System.Windows.Threading;
namespace System.Windows.Markup
#endif
{
///Exception class for parser specific exceptions
[Serializable]
#if PBTCOMPILER
internal class XamlParseException : SystemException
#else
public class XamlParseException : SystemException
#endif
{
#region Public
#region Constructors
///
/// Constructor
///
public XamlParseException() : base ()
{
}
///
/// Constructor
///
///
/// Exception message
///
public XamlParseException(string message) : base (message)
{
}
///
/// Constructor
///
/// Exception message
/// exception occured
public XamlParseException(string message, Exception innerException) : base(message, innerException)
{
}
///
/// Constructor
///
///
/// Exception message
///
///
/// lineNumber the exception occured at
///
///
/// LinePosition the Exception occured at.
///
///
public XamlParseException(string message,int lineNumber, int linePosition) : this (message)
{
_lineNumber = lineNumber;
_linePosition = linePosition;
}
///
/// Constructor
///
///
/// Exception message
///
///
/// lineNumber the exception occured at
///
///
/// LinePosition the Exception occured at.
///
///
/// original Exception that was thrown.
///
public XamlParseException(string message,int lineNumber, int linePosition,Exception innerException)
: this(message, innerException)
{
_lineNumber = lineNumber;
_linePosition = linePosition;
}
#endregion Constructors
#region Properties
///
/// LineNumber that the exception occured on.
///
public int LineNumber
{
get { return _lineNumber; }
}
///
/// LinePosition that the exception occured on.
///
public int LinePosition
{
get { return _linePosition; }
}
///
/// If this is set, it indicates that the Xaml exception occurred
/// in the context of a dictionary item, and this was the Xaml Key
/// value of that item.
///
public object KeyContext
{
#if PBTCOMPILER
set { _keyContext= value; }
#else
get { return _keyContext; }
internal set { _keyContext= value; }
#endif
}
///
/// If this is set, it indicates that the Xaml exception occurred
/// in the context of an object with a Xaml Uid set, and this was the
/// value of that Uid.
///
public string UidContext
{
#if PBTCOMPILER
set { _uidContext = value; }
#else
get { return _uidContext; }
internal set { _uidContext = value; }
#endif
}
///
/// If this is set, it indicates that the Xaml exception occurred
/// in the context of an object with a Xaml Name set, and this was the
/// value of that name.
///
public string NameContext
{
#if PBTCOMPILER
set { _nameContext = value; }
#else
get { return _nameContext; }
internal set { _nameContext = value; }
#endif
}
///
/// The BaseUri in effect at the point of the exception.
///
public Uri BaseUri
{
#if PBTCOMPILER
set { _baseUri = value; }
#else
get { return _baseUri; }
internal set { _baseUri = value; }
#endif
}
#endregion Properties
#endregion Public
#region Private
#region Serialization
///
/// Internal constructor used for serialization when marshalling an
/// exception of this type across and AppDomain or machine boundary.
///
///
/// Contains all the information needed to serialize or deserialize
/// the object.
///
///
/// Describes the source and destination of a given serialized stream,
/// as well as a means for serialization to retain that context and an
/// additional caller-defined context.
///
//CASRemoval:[SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter=true)]
protected XamlParseException(
SerializationInfo info,
StreamingContext context
)
: base(info, context)
{
_lineNumber = info.GetInt32("Line");
_linePosition = info.GetInt32("Position");
}
///
/// Populates a SerializationInfo with the data needed to serialize the target object.
///
///
/// The SerializationInfo to populate with data.
///
///
/// The destination for this serialization.
///
///
///
/// Critical: calls Exception.GetObjectData which LinkDemands
/// TreatAsSafe: We make the corresponding demand here, to ensure that it becomes a full
/// demand.
///
[SecurityCritical, SecurityTreatAsSafe]
#if ! PBTCOMPILER
[SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.SerializationFormatter)]
#else
[SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter=true)]
#endif
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("Line", (Int32)_lineNumber);
info.AddValue("Position", (Int32)_linePosition);
}
#endregion Serialization
#region internal helper methods
#if ! PBTCOMPILER
//
// Return the relative file path for current markup stream or file.
// If the stream comes from assembly resource with .baml extension, this method
// still reports .xaml.
// The purpose of this method is to help developer to debug a failed baml stream.
//
internal static string GetMarkupFilePath(Uri resourceUri)
{
string bamlFilePath = string.Empty;
string xamlFilePath = string.Empty;
if (resourceUri != null)
{
if (resourceUri.IsAbsoluteUri)
{
bamlFilePath = resourceUri.GetComponents(UriComponents.Path, UriFormat.Unescaped);
}
else
{
bamlFilePath = resourceUri.OriginalString;
}
// Replace the .baml with .xaml file extension.
xamlFilePath = bamlFilePath.Replace(BamlExt, XamlExt);
// Confirm the result has a .xaml file extension.
if (-1 == xamlFilePath.LastIndexOf(XamlExt, StringComparison.Ordinal))
xamlFilePath = string.Empty;
}
return xamlFilePath;
}
//
// Get context information at the point of the exception, such as
// names and Uids.
//
internal static void GetObjectContext(
BamlRecordReader bamlRecordReader,
XamlObjectIds currentXamlObjectIds,
XamlObjectIds contextXamlObjectIds,
out Type objectType)
{
object parentObject = null;
GetObjectContext( bamlRecordReader, currentXamlObjectIds, contextXamlObjectIds, out objectType,
out parentObject );
}
internal static void GetObjectContext(
BamlRecordReader bamlRecordReader,
out object parentObject )
{
XamlObjectIds currentXamlObjectIds = new XamlObjectIds();
Type objectType;
GetObjectContext( bamlRecordReader, currentXamlObjectIds, null, out objectType, out parentObject );
}
internal static void GetObjectContext(
BamlRecordReader bamlRecordReader,
XamlObjectIds currentXamlObjectIds,
XamlObjectIds contextXamlObjectIds,
out Type objectType,
out object parentObject)
{
ParserStack contextStack;
ReaderContextStackData readerContextStackData;
parentObject = null;
objectType = null;
// We get context from the reader, so there's nothing to do if we don't
// have one.
if (bamlRecordReader == null)
{
return;
}
contextStack = bamlRecordReader.ContextStack;
if( contextStack.Count == 0 )
{
return;
}
// Walk the reader's context stack and look for context information
// (x:Name, x:Key, and x:Uid).
bool currentObjectElementFound = (currentXamlObjectIds == null); // (See below for usage and comment)
bool parentObjectElementFound = false;
for( int i = contextStack.Count-1; i >= 0; i-- )
{
readerContextStackData = contextStack[i] as ReaderContextStackData;
// First, see if we can fill in the currentXamlObjectIds.
//
// The context stack data has entries for both objects and properties
// E.g. if we're trying to parse "Foo" under >>,
// the CurrentContext will be a property record for the property element
// Button.Background. So the actual current object element will be Button.
// So we check here to find the first object element as we're walking up
// the stack. (Note that we also ignore elements that were injected
// by the parser, and objects that are placeholders.)
if( (!currentObjectElementFound || !parentObjectElementFound )
&&
readerContextStackData.IsObjectElement
&&
(readerContextStackData.ContextFlags & ReaderFlags.CollectionHolder) == 0
&&
(readerContextStackData.ContextFlags & ReaderFlags.InjectedElement) == 0 )
{
if( !currentObjectElementFound )
{
currentObjectElementFound = true;
// Get any/all Ids of the current object element.
currentXamlObjectIds.Name = readerContextStackData.ElementNameOrPropertyName;
currentXamlObjectIds.Uid = readerContextStackData.Uid;
currentXamlObjectIds.Key = readerContextStackData.Key;
// Determine the type of the current object element.
object currentObject = readerContextStackData.ObjectData;
if (currentObject != null)
{
// If this is a FEF, use the FEF's type
if (currentObject is FrameworkElementFactory)
{
objectType = ((FrameworkElementFactory)currentObject).Type;
}
else
{
objectType = currentObject.GetType();
}
}
}
else
{
parentObjectElementFound = true;
parentObject = readerContextStackData.ObjectData;
}
}
// Second, look at all entries in the stack, in search of the nearest
// Ids.
if( contextXamlObjectIds != null )
{
if( contextXamlObjectIds.Name == null && readerContextStackData.ElementNameOrPropertyName != null )
{
contextXamlObjectIds.Name = readerContextStackData.ElementNameOrPropertyName;
}
if( contextXamlObjectIds.Uid == null && readerContextStackData.Uid != null )
{
contextXamlObjectIds.Uid = readerContextStackData.Uid;
}
if( contextXamlObjectIds.Key == null && readerContextStackData.Key != null )
{
contextXamlObjectIds.Key = readerContextStackData.Key;
}
}
}
return;
}
[Flags]
private enum ContextBits { Type=1, File=2, Line=4 };
//
// Apply the context to the original error message.
// The context contains :
// Current markup file
// Current element name in the markup file.
//
internal static string GenerateErrorMessageContext(
int lineNumber,
int linePosition,
Uri baseUri,
XamlObjectIds xamlObjectIds,
Type objectType)
{
string message=" ";
string xamlFile = GetMarkupFilePath(baseUri);
string simpleObjectId = null;
// Calculate the simpleObjectId. Use the object's name, key, Uid, or
// type name, whichever is available (in that order).
if( xamlObjectIds != null )
{
if( xamlObjectIds.Name != null )
{
simpleObjectId = xamlObjectIds.Name;
}
else if( xamlObjectIds.Key != null )
{
simpleObjectId = xamlObjectIds.Key.ToString();
}
else if( xamlObjectIds.Uid != null )
{
simpleObjectId = xamlObjectIds.Uid;
}
}
if( simpleObjectId == null && objectType != null )
{
simpleObjectId = objectType.ToString();
}
ContextBits flags = 0;
if (simpleObjectId != null)
flags |= ContextBits.Type;
if (!String.IsNullOrEmpty(xamlFile))
flags |= ContextBits.File;
if (lineNumber > 0 )
flags |= ContextBits.Line;
switch(flags)
{
case 0:
message = String.Empty;
break;
case ContextBits.Type:
message = SR.Get(SRID.ParserErrorContext_Type, simpleObjectId);
break;
case ContextBits.File:
message = SR.Get(SRID.ParserErrorContext_File, xamlFile);
break;
case ContextBits.Type | ContextBits.File:
message = SR.Get(SRID.ParserErrorContext_Type_File, simpleObjectId, xamlFile);
break;
case ContextBits.Line:
message = SR.Get(SRID.ParserErrorContext_Line, lineNumber, linePosition);
break;
case ContextBits.Type | ContextBits.Line:
message = SR.Get(SRID.ParserErrorContext_Type_Line, simpleObjectId, lineNumber, linePosition);
break;
case ContextBits.File | ContextBits.Line:
message = SR.Get(SRID.ParserErrorContext_File_Line, xamlFile, lineNumber, linePosition);
break;
case ContextBits.Type | ContextBits.File | ContextBits.Line:
message = SR.Get(SRID.ParserErrorContext_Type_File_Line, simpleObjectId, xamlFile, lineNumber, linePosition);
break;
}
return message;
}
#endif
//
// This method creates a XamlParseException and throws it. If provided, it incorporates
// the information such as baseUri and elementName into the exception, possibly in the exception
// message, and always in the XamlParseException itself. When an inner exception is provided,
// we incorporate its Message into the XamlParseException's message.
//
// When an exception is thrown during xaml load (compile), we simply identify its location with
// the line number and position. When an exception is thrown at runtime (baml load),
// we identify its location with as much information as we can, since we don't have line numbers
// available. So the following identifying information is provided, if available: BaseUri,
// nearest x:Uid in context, nearest x:Name, and nearest x:Key.
//
internal static void ThrowException(
string message,
Exception innerException,
int lineNumber,
int linePosition,
Uri baseUri,
XamlObjectIds currentXamlObjectIds,
XamlObjectIds contextXamlObjectIds,
Type objectType
)
{
// If there's an inner exception, we'll append its message to our own.
if( innerException != null && innerException.Message != null )
{
StringBuilder sb = new StringBuilder(message);
if( innerException.Message != String.Empty )
{
sb.Append( " " );
}
sb.Append( innerException.Message );
message = sb.ToString();
}
// If we have line numbers, then we are
// parsing a xaml file where the line number has been explicitly set, so
// throw a xaml exception. Otherwise we are parsing a baml file, or we
// don't know what the line number is.
XamlParseException xamlParseException;
#if !PBTCOMPILER
string contextMessage = XamlParseException.GenerateErrorMessageContext(
lineNumber,
linePosition,
baseUri,
currentXamlObjectIds,
objectType);
message = message + " " + contextMessage;
#endif
// If the exception was a XamlParse exception on the other
// side of a Reflection Invoke, then just pull up the Parse exception.
if (innerException is TargetInvocationException && innerException.InnerException is XamlParseException)
{
xamlParseException = (XamlParseException)innerException.InnerException;
}
else
{
if (lineNumber > 0 )
{
xamlParseException = new XamlParseException(message, lineNumber, linePosition, innerException);
}
else
{
#if PBTCOMPILER
throw new InvalidOperationException(message);
#else
xamlParseException = new XamlParseException(message, innerException);
#endif
}
}
// Fill in the exception with some more runtime-context information.
if (contextXamlObjectIds != null)
{
xamlParseException.NameContext = contextXamlObjectIds.Name;
xamlParseException.UidContext = contextXamlObjectIds.Uid;
xamlParseException.KeyContext = contextXamlObjectIds.Key;
}
xamlParseException.BaseUri = baseUri;
#if !PBTCOMPILER
if( TraceMarkup.IsEnabled )
{
TraceMarkup.TraceActivityItem( TraceMarkup.ThrowException,
xamlParseException );
}
#endif
throw xamlParseException;
}
//
// Runtime (baml loader) ThrowException wrapper that takes an inner exception and
// incorporates context from the ParserContext.
//
#if !PBTCOMPILER
internal static void ThrowException(ParserContext parserContext, int lineNumber, int linePosition, string message, Exception innerException)
{
if( parserContext != null )
{
Type objectType;
XamlObjectIds currentXamlObjectIds = new XamlObjectIds();
XamlObjectIds contextXamlObjectIds = new XamlObjectIds();
GetObjectContext(
parserContext.BamlReader,
currentXamlObjectIds,
contextXamlObjectIds,
out objectType );
ThrowException(
message,
innerException,
lineNumber,
linePosition,
parserContext.BaseUri,
currentXamlObjectIds,
contextXamlObjectIds,
objectType );
}
else
{
ThrowException(
message,
innerException,
lineNumber,
linePosition );
}
}
#endif
//
// Convenience ThrowException wrapper that just takes the message, inner exception, and line number.
//
internal static void ThrowException(
string message,
Exception innerException,
int lineNumber,
int linePosition )
{
ThrowException( message, innerException, lineNumber, linePosition,
null, null, null, null );
}
#endregion internal helper methods
#region const
internal const string BamlExt = ".baml";
internal const string XamlExt = ".xaml";
#endregion const
#region Data
int _lineNumber = 0;
int _linePosition = 0;
object _keyContext = null;
string _uidContext = null;
string _nameContext = null;
Uri _baseUri = null;
#endregion Data
#endregion Private
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.