我对来自J Wynia的示例进行了一些尝试。非常感谢。
我更改了VirtualPathProvider的扩展,使用静态构造函数创建一个列表,其中包含系统中各个dll中以.aspx结尾的所有可用资源。虽然这很费力,但我们只需要做一次。
这可能完全滥用了VirtualFiles的使用方式;-)
最终你会得到:
private static IDictionary resourceVirtualFile;
字符串是虚拟路径。
下面的代码假设.aspx文件的命名空间很简单,但在简单情况下它可以工作。好处是您不必创建复杂的视图路径,它们是从资源名称创建的。
class ResourceVirtualFile : VirtualFile
{
string path;
string assemblyName;
string resourceName;
public ResourceVirtualFile(
string virtualPath,
string AssemblyName,
string ResourceName)
: base(virtualPath)
{
path = VirtualPathUtility.ToAppRelative(virtualPath);
assemblyName = AssemblyName;
resourceName = ResourceName;
}
public override Stream Open()
{
assemblyName = Path.Combine(HttpRuntime.BinDirectory, assemblyName + ".dll");
Assembly assembly = Assembly.ReflectionOnlyLoadFrom(assemblyName);
if (assembly != null)
{
Stream resourceStream = assembly.GetManifestResourceStream(resourceName);
if (resourceStream == null)
throw new ArgumentException("Cannot find resource: " + resourceName);
return resourceStream;
}
throw new ArgumentException("Cannot find assembly: " + assemblyName);
}
private static string CreateVirtualPath(string AssemblyName, string ResourceName)
{
string path = ResourceName.Substring(AssemblyName.Length);
path = path.Replace(".aspx", "").Replace(".", "/");
return string.Format("~{0}.aspx", path);
}
public static IDictionary<string, VirtualFile> FindAllResources()
{
Dictionary<string, VirtualFile> files = new Dictionary<string, VirtualFile>();
string[] assemblyFilePaths = Directory.GetFiles(HttpRuntime.BinDirectory, "*.dll");
foreach (string assemblyFilePath in assemblyFilePaths)
{
string assemblyName = Path.GetFileNameWithoutExtension(assemblyFilePath);
Assembly assembly = Assembly.ReflectionOnlyLoadFrom(assemblyFilePath);
string[] resourceNames = assembly.GetManifestResourceNames();
foreach (string resourceName in resourceNames)
{
if (resourceName.EndsWith(".aspx"))
{
string virtualPath = CreateVirtualPath(assemblyName, resourceName);
files.Add(virtualPath, new ResourceVirtualFile(virtualPath, assemblyName, resourceName));
}
}
}
return files;
}
}
您可以在扩展的VirtualPathProvider中执行以下操作:
private bool IsExtended(string virtualPath)
{
String checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
return resourceVirtualFile.ContainsKey(checkPath);
}
public override bool FileExists(string virtualPath)
{
return (IsExtended(virtualPath) || base.FileExists(virtualPath));
}
public override VirtualFile GetFile(string virtualPath)
{
string withTilda = string.Format("~{0}", virtualPath);
if (resourceVirtualFile.ContainsKey(withTilda))
return resourceVirtualFile[withTilda];
return base.GetFile(virtualPath);
}