internal class AppResourcesCompiler
{
const string cachePrefix = "@@LocalResourcesAssemblies";
+ public const string DefaultCultureKey = ".:!DefaultCulture!:.";
bool isGlobal;
HttpContext context;
AppResourceFilesCollection files;
string tempDirectory;
string virtualPath;
+ Dictionary <string, List <string>> cultureFiles;
string TempDirectory {
get {
return (tempDirectory = AppDomain.CurrentDomain.SetupInformation.DynamicBase);
}
}
+
+ public Dictionary <string, List <string>> CultureFiles {
+ get { return cultureFiles; }
+ }
public AppResourcesCompiler (HttpContext context)
{
this.context = context;
this.isGlobal = true;
this.files = new AppResourceFilesCollection (context);
+ this.cultureFiles = new Dictionary <string, List <string>> ();
}
public AppResourcesCompiler (string virtualPath)
this.virtualPath = virtualPath;
this.isGlobal = false;
this.files = new AppResourceFilesCollection (HttpContext.Current.Request.MapPath (virtualPath));
+ this.cultureFiles = new Dictionary <string, List <string>> ();
}
public Assembly Compile ()
if (assemblyPath == null)
throw new ApplicationException ("Failed to create global resources assembly");
- CompilationSection config = WebConfigurationManager.GetSection ("system.web/compilation") as CompilationSection;
- if (config == null || !CodeDomProvider.IsDefinedLanguage (config.DefaultLanguage))
- throw new ApplicationException ("Could not get the default compiler.");
- CompilerInfo ci = CodeDomProvider.GetCompilerInfo (config.DefaultLanguage);
- if (ci == null || !ci.IsCodeDomProviderTypeValid)
- throw new ApplicationException ("Failed to obtain the default compiler information.");
-
- CompilerParameters cp = ci.CreateDefaultCompilerParameters ();
- cp.OutputAssembly = assemblyPath;
- cp.GenerateExecutable = false;
- cp.TreatWarningsAsErrors = true;
- cp.IncludeDebugInformation = config.Debug;
-
- List <string>[] fileGroups = GroupGlobalFiles (cp);
+ List <string>[] fileGroups = GroupGlobalFiles ();
if (fileGroups == null || fileGroups.Length == 0)
return null;
-
+
CodeCompileUnit unit = new CodeCompileUnit ();
CodeNamespace ns = new CodeNamespace (null);
ns.Imports.Add (new CodeNamespaceImport ("System"));
ns.Imports.Add (new CodeNamespaceImport ("System.Resources"));
unit.Namespaces.Add (ns);
- CodeDomProvider provider;
- provider = ci.CreateProvider ();
- if (provider == null)
- throw new ApplicationException ("Failed to instantiate the default compiler.");
+ AppResourcesAssemblyBuilder builder = new AppResourcesAssemblyBuilder ("App_GlobalResources", assemblyPath,
+ this);
+ CodeDomProvider provider = builder.Provider;
Dictionary <string,bool> assemblies = new Dictionary<string,bool> ();
foreach (List<string> ls in fileGroups)
DomFromResource (ls [0], unit, assemblies, provider);
+
foreach (KeyValuePair<string,bool> de in assemblies)
unit.ReferencedAssemblies.Add (de.Key);
- AssemblyBuilder abuilder = new AssemblyBuilder (provider);
- abuilder.AddCodeCompileUnit (unit);
-
- CompilerResults results = abuilder.BuildAssembly (cp);
- Assembly ret = null;
+ builder.Build (unit);
+ HttpContext.AppGlobalResourcesAssembly = builder.MainAssembly;
- if (results.Errors.Count == 0) {
- ret = results.CompiledAssembly;
- BuildManager.TopLevelAssemblies.Add (ret);
- HttpContext.AppGlobalResourcesAssembly = ret;
- } else {
- if (context.IsCustomErrorEnabled)
- throw new ApplicationException ("An error occurred while compiling global resources.");
- throw new CompilationException (null, results.Errors, null);
- }
- HttpRuntime.WritePreservationFile (ret, "App_GlobalResources");
- HttpRuntime.EnableAssemblyMapping (true);
-
- return ret;
+ return builder.MainAssembly;
}
Assembly CompileLocal ()
"dll",
OnCreateRandomFile) as string;
if (assemblyPath == null)
- throw new ApplicationException ("Failed to create global resources assembly");
-
- CompilationSection config = WebConfigurationManager.GetSection ("system.web/compilation") as CompilationSection;
- if (config == null || !CodeDomProvider.IsDefinedLanguage (config.DefaultLanguage))
- throw new ApplicationException ("Could not get the default compiler.");
- CompilerInfo ci = CodeDomProvider.GetCompilerInfo (config.DefaultLanguage);
- if (ci == null || !ci.IsCodeDomProviderTypeValid)
- throw new ApplicationException ("Failed to obtain the default compiler information.");
-
- CompilerParameters cp = ci.CreateDefaultCompilerParameters ();
- cp.OutputAssembly = assemblyPath;
- cp.GenerateExecutable = false;
- cp.TreatWarningsAsErrors = true;
- cp.IncludeDebugInformation = config.Debug;
+ throw new ApplicationException ("Failed to create local resources assembly");
List<AppResourceFileInfo> files = this.files.Files;
foreach (AppResourceFileInfo arfi in files)
- GetResourceFile (arfi, cp, true);
+ GetResourceFile (arfi, true);
- CodeDomProvider provider;
- provider = ci.CreateProvider ();
- if (provider == null)
- throw new ApplicationException ("Failed to instantiate the default compiler.");
-
- AssemblyBuilder abuilder = new AssemblyBuilder (provider);
- CompilerResults results = abuilder.BuildAssembly (cp);
- Assembly ret = null;
+ AppResourcesAssemblyBuilder builder = new AppResourcesAssemblyBuilder ("App_LocalResources", assemblyPath,
+ this);
+ builder.Build ();
+ Assembly ret = builder.MainAssembly;
- if (results.Errors.Count == 0) {
- ret = results.CompiledAssembly;
+ if (ret != null)
AddAssemblyToCache (virtualPath, ret);
- } else {
- if (context.IsCustomErrorEnabled)
- throw new ApplicationException ("An error occurred while compiling global resources.");
- throw new CompilationException (null, results.Errors, null);
- }
return ret;
}
{
Dictionary <string, Assembly> cache;
- cache = HttpRuntime.Cache[cachePrefix] as Dictionary <string, Assembly>;
+ cache = HttpRuntime.InternalCache[cachePrefix] as Dictionary <string, Assembly>;
if (cache == null || !cache.ContainsKey (path))
return null;
return cache [path];
void AddAssemblyToCache (string path, Assembly asm)
{
- Cache runtimeCache = HttpRuntime.Cache;
+ Cache runtimeCache = HttpRuntime.InternalCache;
Dictionary <string, Assembly> cache;
cache = runtimeCache[cachePrefix] as Dictionary <string, Assembly>;
return ret;
}
- bool IsFileCultureValid (string fileName)
+ string IsFileCultureValid (string fileName)
{
string tmp = Path.GetFileNameWithoutExtension (fileName);
tmp = Path.GetExtension (tmp);
tmp = tmp.Substring (1);
try {
CultureInfo.GetCultureInfo (tmp);
- return true;
+ return tmp;
} catch {
- return false;
+ return null;
}
}
- return false;
+ return null;
}
-
- string GetResourceFile (AppResourceFileInfo arfi, CompilerParameters cp, bool local)
+
+ string GetResourceFile (AppResourceFileInfo arfi, bool local)
{
string resfile;
if (arfi.Kind == AppResourceFileKind.ResX)
resfile = CompileResource (arfi, local);
else
resfile = arfi.Info.FullName;
- if (!String.IsNullOrEmpty (resfile))
- cp.EmbeddedResources.Add (resfile);
+ if (!String.IsNullOrEmpty (resfile)) {
+ string culture = IsFileCultureValid (resfile);
+ if (culture == null)
+ culture = DefaultCultureKey;
+
+ List <string> cfiles;
+ if (cultureFiles.ContainsKey (culture))
+ cfiles = cultureFiles [culture];
+ else {
+ cfiles = new List <string> (1);
+ cultureFiles [culture] = cfiles;
+ }
+ cfiles.Add (resfile);
+ }
+
return resfile;
}
- List <string>[] GroupGlobalFiles (CompilerParameters cp)
+ List <string>[] GroupGlobalFiles ()
{
List<AppResourceFileInfo> files = this.files.Files;
List<List<string>> groups = new List<List<string>> ();
filedots = CountChars ('.', tmp);
if (filedots == basedots + 1 && tmp.StartsWith (basename)) {
- if (IsFileCultureValid (s2)) {
+ if (IsFileCultureValid (s2) != null) {
// A valid translated file for this name
defaultFile = arfi;
break;
}
if (defaultFile != null) {
List<string> al = new List<string> ();
- al.Add (GetResourceFile (arfi, cp, false));
+ al.Add (GetResourceFile (arfi, false));
arfi.Seen = true;
groups.Add (al);
continue;
tmp2 = arfi.Info.Name;
if (tmp2.StartsWith (tmp)) {
- al.Add (GetResourceFile (arfi, cp, false));
+ al.Add (GetResourceFile (arfi, false));
arfi.Seen = true;
}
}
if (arfi.Seen)
continue;
- if (IsFileCultureValid (arfi.Info.FullName))
+ if (IsFileCultureValid (arfi.Info.FullName) != null)
continue; // Culture found, we reject the file
// A single default file, create a group
List<string> al = new List<string> ();
- al.Add (GetResourceFile (arfi, cp, false));
+ al.Add (GetResourceFile (arfi, false));
groups.Add (al);
}
groups.Sort (lcList);
nsname = "Resources";
} else {
if (!nsname.StartsWith ("Resources", StringComparison.InvariantCulture))
- nsname = String.Format ("Resources.{0}", nsname);
+ nsname = String.Concat ("Resources.", nsname);
classname = classname.Substring(1);
}
cls.IsClass = true;
cls.TypeAttributes = TypeAttributes.Public | TypeAttributes.Sealed;
- CodeMemberField cmf = new CodeMemberField (typeof(CultureInfo), "culture");
+ CodeMemberField cmf = new CodeMemberField (typeof(CultureInfo), "_culture");
cmf.InitExpression = new CodePrimitiveExpression (null);
cmf.Attributes = MemberAttributes.Private | MemberAttributes.Final | MemberAttributes.Static;
cls.Members.Add (cmf);
- cmf = new CodeMemberField (typeof(ResourceManager), "resourceManager");
+ cmf = new CodeMemberField (typeof(ResourceManager), "_resourceManager");
cmf.InitExpression = new CodePrimitiveExpression (null);
cmf.Attributes = MemberAttributes.Private | MemberAttributes.Final | MemberAttributes.Static;
cls.Members.Add (cmf);
cmp.HasGet = true;
cmp.HasSet = true;
cmp.Type = new CodeTypeReference (typeof(CultureInfo));
- CodePropertyGenericGet (cmp.GetStatements, "culture", classname);
- CodePropertyGenericSet (cmp.SetStatements, "culture", classname);
+ CodePropertyGenericGet (cmp.GetStatements, "_culture", classname);
+ CodePropertyGenericSet (cmp.SetStatements, "_culture", classname);
cls.Members.Add (cmp);
// Add the resource properties
CodeStatement st;
CodeExpression exp;
- exp = new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (typename), "resourceManager");
+ exp = new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (typename), "_resourceManager");
st = new CodeConditionStatement (
new CodeBinaryOperatorExpression (
exp,
gotstr ? "GetString" : "GetObject",
new CodeExpression [] { new CodePrimitiveExpression (resname),
new CodeFieldReferenceExpression (
- new CodeTypeReferenceExpression (typename), "culture") });
+ new CodeTypeReferenceExpression (typename), "_culture") });
st = new CodeVariableDeclarationStatement (
restype,
"obj",