RazorEngine icon indicating copy to clipboard operation
RazorEngine copied to clipboard

fixed issue with Assembly.Location throwing

Open defr0zen opened this issue 7 years ago • 6 comments

Assembly.Location could throw. In my case, I am trying to use RazorEngine in an Azure Function, which loads some native Edge dlls for JavaScript interop. These assemblies are loaded into the domain, however, calling Assembly.Location on them throws an exception.

I was thinking to use a custom resolver, however, this code is also used in the exceptions, and it is not trivial to use the custom resolver in the exception constructors. Hence such quick fix.

defr0zen avatar May 03 '17 19:05 defr0zen

Guys any temp workaround till the time this pull is merged into the master?

shyamal890 avatar Jan 28 '18 15:01 shyamal890

@shyamal890 Yes the assembly-resolver can be configured so you can just copy it to your code and configure it.

matthid avatar Feb 03 '18 10:02 matthid

@matthid I created a new cs file with the following code. However, CompilerServiceBase.DynamicTemplateNamespace gives an error since it's inaccessible due to its protection level.

namespace RazorEngine.Compilation.ReferenceResolver
{
    public class UseCurrentAssembliesReferenceResolver : IReferenceResolver
    {
        /// <summary>
        /// See <see cref="IReferenceResolver.GetReferences"/>
        /// </summary>
        /// <param name="context"></param>
        /// <param name="includeAssemblies"></param>
        /// <returns></returns>
        public IEnumerable<CompilerReference> GetReferences(TypeContext context = null, IEnumerable<CompilerReference> includeAssemblies = null)
        {
            return CompilerServicesUtility
                   .GetLoadedAssemblies()
                   .Where(IsValidAssembly)
                   .GroupBy(a => a.GetName().Name).Select(grp => grp.First(y => y.GetName().Version == grp.Max(x => x.GetName().Version))) // only select distinct assemblies based on FullName to avoid loading duplicate assemblies
                   .Select(a => CompilerReference.From(a))
                   .Concat(includeAssemblies ?? Enumerable.Empty<CompilerReference>());
        }

        private static bool IsValidAssembly(System.Reflection.Assembly a)
        {
            try
            {
                return !a.IsDynamic && File.Exists(a.Location) && !a.Location.Contains(CompilerServiceBase.DynamicTemplateNamespace);
            }
            catch
            {
                return false;
            }
        }

    }
}

shyamal890 avatar Feb 05 '18 12:02 shyamal890

@shyamal890 https://github.com/Antaris/RazorEngine/blob/a2a17c56322042db17816569db778fe873d2d7ec/src/source/RazorEngine.Core/Compilation/CompilerServiceBase.cs#L34

matthid avatar Feb 05 '18 12:02 matthid

when will this be merged?

harmandeol avatar Apr 05 '18 06:04 harmandeol

private static bool IsValidAssembly(System.Reflection.Assembly a)
        {
            //Azure function is failing when try to accessl location of this dll
            var skipByName = new[] {"edge_nativeclr"};
            return !skipByName.All(c => a.FullName.StartsWith(c)) && !a.IsDynamic && File.Exists(a.Location) &&
                   !a.Location.Contains(DynamicTemplateNamespace);
        }

Basiclly this fixes my problem

vovikdrg avatar May 16 '18 02:05 vovikdrg