You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@ -0,0 +1,354 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="ResourceExpressionBuilder.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web.Compilation {
|
||||
using System;
|
||||
using System.Security.Permissions;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.CodeDom;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Web.Caching;
|
||||
using System.Web.Compilation;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Hosting;
|
||||
using System.Web.Util;
|
||||
using System.Web.UI;
|
||||
|
||||
|
||||
[ExpressionPrefix("Resources")]
|
||||
[ExpressionEditor("System.Web.UI.Design.ResourceExpressionEditor, " + AssemblyRef.SystemDesign)]
|
||||
public class ResourceExpressionBuilder : ExpressionBuilder {
|
||||
|
||||
private static ResourceProviderFactory s_resourceProviderFactory;
|
||||
|
||||
public override bool SupportsEvaluate {
|
||||
get {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static ResourceExpressionFields ParseExpression(string expression) {
|
||||
return ParseExpressionInternal(expression);
|
||||
}
|
||||
|
||||
public override object ParseExpression(string expression, Type propertyType, ExpressionBuilderContext context) {
|
||||
ResourceExpressionFields fields = null;
|
||||
|
||||
try {
|
||||
fields = ParseExpressionInternal(expression);
|
||||
}
|
||||
catch {
|
||||
}
|
||||
|
||||
// If the parsing failed for any reason throw an error
|
||||
if (fields == null) {
|
||||
throw new HttpException(
|
||||
SR.GetString(SR.Invalid_res_expr, expression));
|
||||
}
|
||||
|
||||
// The resource expression was successfully parsed. We now need to check whether
|
||||
// the resource object actually exists in the neutral culture
|
||||
|
||||
// If we don't have a virtual path, we can't check that the resource exists.
|
||||
// This happens in the designer.
|
||||
if (context.VirtualPathObject != null) {
|
||||
|
||||
IResourceProvider resourceProvider = GetResourceProvider(fields, VirtualPath.Create(context.VirtualPath));
|
||||
object o = null;
|
||||
|
||||
if (resourceProvider != null) {
|
||||
try {
|
||||
o = resourceProvider.GetObject(fields.ResourceKey, CultureInfo.InvariantCulture);
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
|
||||
// If it doesn't throw an exception
|
||||
if (o == null) {
|
||||
throw new HttpException(
|
||||
SR.GetString(SR.Res_not_found, fields.ResourceKey));
|
||||
}
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
|
||||
public override CodeExpression GetCodeExpression(BoundPropertyEntry entry,
|
||||
object parsedData, ExpressionBuilderContext context) {
|
||||
|
||||
// Retrieve our parsed data
|
||||
ResourceExpressionFields fields = (ResourceExpressionFields) parsedData;
|
||||
|
||||
// If there is no classKey, it's a page-level resource
|
||||
if (fields.ClassKey.Length == 0) {
|
||||
return GetPageResCodeExpression(fields.ResourceKey, entry);
|
||||
}
|
||||
|
||||
// Otherwise, it's a global resource
|
||||
return GetAppResCodeExpression(fields.ClassKey, fields.ResourceKey, entry);
|
||||
}
|
||||
|
||||
|
||||
public override object EvaluateExpression(object target, BoundPropertyEntry entry,
|
||||
object parsedData, ExpressionBuilderContext context) {
|
||||
|
||||
// Retrieve our parsed data
|
||||
ResourceExpressionFields fields = (ResourceExpressionFields) parsedData;
|
||||
|
||||
IResourceProvider resourceProvider = GetResourceProvider(fields, context.VirtualPathObject);
|
||||
|
||||
if (entry.Type == typeof(string))
|
||||
return GetResourceObject(resourceProvider, fields.ResourceKey, null /*culture*/);
|
||||
|
||||
// If the property is not of type string, pass in extra information
|
||||
// so that the resource value will be converted to the right type
|
||||
return GetResourceObject(resourceProvider, fields.ResourceKey, null /*culture*/,
|
||||
entry.DeclaringType, entry.PropertyInfo.Name);
|
||||
}
|
||||
|
||||
private CodeExpression GetAppResCodeExpression(string classKey, string resourceKey, BoundPropertyEntry entry) {
|
||||
// We generate the following
|
||||
// this.GetGlobalResourceObject(classKey)
|
||||
CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression();
|
||||
expr.Method.TargetObject = new CodeThisReferenceExpression();
|
||||
|
||||
expr.Method.MethodName = "GetGlobalResourceObject";
|
||||
expr.Parameters.Add(new CodePrimitiveExpression(classKey));
|
||||
expr.Parameters.Add(new CodePrimitiveExpression(resourceKey));
|
||||
|
||||
// If the property is not of type string, it will need to be converted
|
||||
if (entry.Type != typeof(string) && entry.Type != null) {
|
||||
expr.Parameters.Add(new CodeTypeOfExpression(entry.DeclaringType));
|
||||
expr.Parameters.Add(new CodePrimitiveExpression(entry.PropertyInfo.Name));
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
private CodeExpression GetPageResCodeExpression(string resourceKey, BoundPropertyEntry entry) {
|
||||
// We generate of the following
|
||||
// this.GetLocalResourceObject(resourceKey)
|
||||
CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression();
|
||||
expr.Method.TargetObject = new CodeThisReferenceExpression();
|
||||
|
||||
expr.Method.MethodName = "GetLocalResourceObject";
|
||||
expr.Parameters.Add(new CodePrimitiveExpression(resourceKey));
|
||||
|
||||
// If the property is not of type string, it will need to be converted
|
||||
if (entry.Type != typeof(string) && entry.Type != null) {
|
||||
expr.Parameters.Add(new CodeTypeOfExpression(entry.DeclaringType));
|
||||
expr.Parameters.Add(new CodePrimitiveExpression(entry.PropertyInfo.Name));
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
internal static object GetGlobalResourceObject(string classKey, string resourceKey) {
|
||||
return GetGlobalResourceObject(classKey, resourceKey, null /*objType*/, null /*propName*/, null /*culture*/);
|
||||
}
|
||||
|
||||
internal static object GetGlobalResourceObject(string classKey,
|
||||
string resourceKey, Type objType, string propName, CultureInfo culture) {
|
||||
|
||||
IResourceProvider resourceProvider = GetGlobalResourceProvider(classKey);
|
||||
return GetResourceObject(resourceProvider, resourceKey, culture,
|
||||
objType, propName);
|
||||
}
|
||||
|
||||
internal static object GetResourceObject(IResourceProvider resourceProvider,
|
||||
string resourceKey, CultureInfo culture) {
|
||||
return GetResourceObject(resourceProvider, resourceKey, culture,
|
||||
null /*objType*/, null /*propName*/);
|
||||
}
|
||||
|
||||
internal static object GetResourceObject(IResourceProvider resourceProvider,
|
||||
string resourceKey, CultureInfo culture, Type objType, string propName) {
|
||||
|
||||
if (resourceProvider == null)
|
||||
return null;
|
||||
|
||||
object o = resourceProvider.GetObject(resourceKey, culture);
|
||||
|
||||
// If no objType/propName was provided, return the object as is
|
||||
if (objType == null)
|
||||
return o;
|
||||
|
||||
// Also, if the object from the resource is not a string, return it as is
|
||||
string s = o as String;
|
||||
if (s == null)
|
||||
return o;
|
||||
|
||||
// If they were provided, perform the appropriate conversion
|
||||
return ObjectFromString(s, objType, propName);
|
||||
}
|
||||
|
||||
private static object ObjectFromString(string value, Type objType, string propName) {
|
||||
|
||||
// Get the PropertyDescriptor for the property
|
||||
PropertyDescriptor pd = TypeDescriptor.GetProperties(objType)[propName];
|
||||
Debug.Assert(pd != null);
|
||||
if (pd == null) return null;
|
||||
|
||||
// Get its type descriptor
|
||||
TypeConverter converter = pd.Converter;
|
||||
Debug.Assert(converter != null);
|
||||
if (converter == null) return null;
|
||||
|
||||
// Perform the conversion
|
||||
return converter.ConvertFromInvariantString(value);
|
||||
}
|
||||
|
||||
// The following syntaxes are accepted for the expression
|
||||
// resourceKey
|
||||
// classKey, resourceKey
|
||||
//
|
||||
private static ResourceExpressionFields ParseExpressionInternal(string expression) {
|
||||
string classKey = null;
|
||||
string resourceKey = null;
|
||||
|
||||
int len = expression.Length;
|
||||
if (len == 0) {
|
||||
return new ResourceExpressionFields(classKey, resourceKey);
|
||||
}
|
||||
|
||||
// Split the comma separated string
|
||||
string[] parts = expression.Split(',');
|
||||
|
||||
int numOfParts = parts.Length;
|
||||
|
||||
if (numOfParts > 2) return null;
|
||||
|
||||
if (numOfParts == 1) {
|
||||
resourceKey = parts[0].Trim();
|
||||
}
|
||||
else {
|
||||
classKey = parts[0].Trim();
|
||||
resourceKey = parts[1].Trim();
|
||||
}
|
||||
|
||||
return new ResourceExpressionFields(classKey, resourceKey);
|
||||
}
|
||||
|
||||
private static IResourceProvider GetResourceProvider(ResourceExpressionFields fields,
|
||||
VirtualPath virtualPath) {
|
||||
// If there is no classKey, it's a page-level resource
|
||||
if (fields.ClassKey.Length == 0) {
|
||||
return GetLocalResourceProvider(virtualPath);
|
||||
}
|
||||
|
||||
// Otherwise, it's a global resource
|
||||
return GetGlobalResourceProvider(fields.ClassKey);
|
||||
}
|
||||
|
||||
private static void EnsureResourceProviderFactory() {
|
||||
if (s_resourceProviderFactory != null)
|
||||
return;
|
||||
|
||||
Type t = null;
|
||||
GlobalizationSection globConfig = RuntimeConfig.GetAppConfig().Globalization;
|
||||
t = globConfig.ResourceProviderFactoryTypeInternal;
|
||||
|
||||
// If we got a type from config, use it. Otherwise, use default factory
|
||||
if (t == null) {
|
||||
s_resourceProviderFactory = new ResXResourceProviderFactory();
|
||||
}
|
||||
else {
|
||||
s_resourceProviderFactory = (ResourceProviderFactory) HttpRuntime.CreatePublicInstance(t);
|
||||
}
|
||||
}
|
||||
|
||||
private static IResourceProvider GetGlobalResourceProvider(string classKey) {
|
||||
string fullClassName = BaseResourcesBuildProvider.DefaultResourcesNamespace +
|
||||
"." + classKey;
|
||||
|
||||
// If we have it cached, return it
|
||||
CacheInternal cacheInternal = System.Web.HttpRuntime.CacheInternal;
|
||||
string cacheKey = CacheInternal.PrefixResourceProvider + fullClassName;
|
||||
IResourceProvider resourceProvider = cacheInternal[cacheKey] as IResourceProvider;
|
||||
if (resourceProvider != null) {
|
||||
return resourceProvider;
|
||||
}
|
||||
|
||||
EnsureResourceProviderFactory();
|
||||
resourceProvider = s_resourceProviderFactory.CreateGlobalResourceProvider(classKey);
|
||||
|
||||
// Cache it
|
||||
cacheInternal.UtcInsert(cacheKey, resourceProvider);
|
||||
|
||||
return resourceProvider;
|
||||
}
|
||||
|
||||
// Get the page-level IResourceProvider
|
||||
internal static IResourceProvider GetLocalResourceProvider(TemplateControl templateControl) {
|
||||
return GetLocalResourceProvider(templateControl.VirtualPath);
|
||||
}
|
||||
|
||||
// Get the page-level IResourceProvider
|
||||
internal static IResourceProvider GetLocalResourceProvider(VirtualPath virtualPath) {
|
||||
|
||||
// If we have it cached, return it (it may be null if there are no local resources)
|
||||
CacheInternal cacheInternal = System.Web.HttpRuntime.CacheInternal;
|
||||
string cacheKey = CacheInternal.PrefixResourceProvider + virtualPath.VirtualPathString;
|
||||
IResourceProvider resourceProvider = cacheInternal[cacheKey] as IResourceProvider;
|
||||
if (resourceProvider != null) {
|
||||
return resourceProvider;
|
||||
}
|
||||
|
||||
EnsureResourceProviderFactory();
|
||||
resourceProvider = s_resourceProviderFactory.CreateLocalResourceProvider(virtualPath.VirtualPathString);
|
||||
|
||||
// Cache it
|
||||
cacheInternal.UtcInsert(cacheKey, resourceProvider);
|
||||
|
||||
return resourceProvider;
|
||||
}
|
||||
|
||||
// Create a ResourceExpressionFields without actually parsing any string. This
|
||||
// is used for 'automatic' resources, where we already have the pieces of
|
||||
// relevant data.
|
||||
internal static object GetParsedData(string resourceKey) {
|
||||
return new ResourceExpressionFields(String.Empty, resourceKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Holds the fields parsed from a resource expression (e.g. classKey, resourceKey)
|
||||
public sealed class ResourceExpressionFields {
|
||||
private string _classKey;
|
||||
private string _resourceKey;
|
||||
|
||||
internal ResourceExpressionFields(string classKey, string resourceKey) {
|
||||
_classKey = classKey;
|
||||
_resourceKey = resourceKey;
|
||||
}
|
||||
|
||||
public string ClassKey {
|
||||
get {
|
||||
if (_classKey == null) {
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
return _classKey;
|
||||
}
|
||||
}
|
||||
|
||||
public string ResourceKey {
|
||||
get {
|
||||
if (_resourceKey == null) {
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
return _resourceKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user