|
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.Xaml.Hosting
{
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using System.Runtime;
using System.Text;
using System.Web;
using System.Web.Compilation;
using System.Web.Hosting;
using System.Xaml;
using System.Xaml.Hosting.Configuration;
using System.Xml;
[BuildProviderAppliesTo(BuildProviderAppliesTo.Web)]
public class XamlBuildProvider : BuildProvider
{
IXamlBuildProviderExtension xamlBuildProviderExtension;
static volatile IXamlBuildProviderExtensionFactory xamlBuildProviderExtensionFactory;
internal new string VirtualPath
{
get { return base.VirtualPath; }
}
public override void GenerateCode(AssemblyBuilder assemblyBuilder)
{
XamlType rootXamlType = GetRootXamlType();
this.GetXamlBuildProviderExtension(rootXamlType);
if (this.xamlBuildProviderExtension != null)
{
using (Stream xamlStream = base.OpenStream())
{
this.xamlBuildProviderExtension.GenerateCode(assemblyBuilder, xamlStream, this);
}
}
}
[Fx.Tag.Throws(typeof(TypeLoadException), "The type resolution of the root element failed.")]
public override Type GetGeneratedType(CompilerResults results)
{
if (this.xamlBuildProviderExtension != null)
{
Type result = this.xamlBuildProviderExtension.GetGeneratedType(results);
if (result != null)
{
return result;
}
}
try
{
XamlType rootXamlType = GetRootXamlType();
if (rootXamlType.IsUnknown)
{
StringBuilder typeName = new StringBuilder();
AppendTypeName(rootXamlType, typeName);
throw FxTrace.Exception.AsError(new TypeLoadException(SR.CouldNotResolveType(typeName)));
}
return rootXamlType.UnderlyingType;
}
catch (XamlParseException ex)
{
throw FxTrace.Exception.AsError(new HttpCompileException(ex.Message, ex));
}
}
public override BuildProviderResultFlags GetResultFlags(CompilerResults results)
{
return BuildProviderResultFlags.ShutdownAppDomainOnChange;
}
private void AppendTypeName(XamlType xamlType, StringBuilder sb)
{
if (!string.IsNullOrEmpty(xamlType.PreferredXamlNamespace))
{
sb.Append("{");
sb.Append(xamlType.PreferredXamlNamespace);
sb.Append("}");
}
sb.Append(xamlType.Name);
if (xamlType.IsGeneric)
{
sb.Append("(");
for (int i = 0; i < xamlType.TypeArguments.Count; i++)
{
AppendTypeName(xamlType.TypeArguments[i], sb);
if (i < xamlType.TypeArguments.Count - 1)
{
sb.Append(", ");
}
}
sb.Append(")");
}
}
XamlType GetRootXamlType()
{
try
{
using (Stream xamlStream = base.OpenStream())
{
XmlReader xmlReader = XmlReader.Create(xamlStream);
XamlXmlReader xamlReader = new XamlXmlReader(xmlReader);
// Read to the root object
while (xamlReader.Read())
{
if (xamlReader.NodeType == XamlNodeType.StartObject)
{
return xamlReader.Type;
}
}
throw FxTrace.Exception.AsError(new HttpCompileException(SR.UnexpectedEof));
}
}
catch (XamlParseException ex)
{
throw FxTrace.Exception.AsError(new HttpCompileException(ex.Message, ex));
}
}
void GetXamlBuildProviderExtension(XamlType rootXamlType)
{
if (rootXamlType.UnderlyingType == null)
{
return;
}
this.GetXamlBuildProviderExtensionFactory(rootXamlType);
if (xamlBuildProviderExtensionFactory != null)
{
this.xamlBuildProviderExtension = xamlBuildProviderExtensionFactory.GetXamlBuildProviderExtension();
}
}
void GetXamlBuildProviderExtensionFactory(XamlType rootXamlType)
{
if (xamlBuildProviderExtensionFactory != null)
{
return;
}
// Get the HttpHandler type
Type httpHandlerType;
XamlHostingConfiguration.TryGetHttpHandlerType(this.VirtualPath, rootXamlType.UnderlyingType, out httpHandlerType);
if (httpHandlerType != null && typeof(IXamlBuildProviderExtensionFactory).IsAssignableFrom(httpHandlerType))
{
xamlBuildProviderExtensionFactory = (IXamlBuildProviderExtensionFactory)Activator.CreateInstance(httpHandlerType,
BindingFlags.CreateInstance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
null, null, null);
}
}
}
}
|