Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 添加在运行时可用于Razor页面的程序集/类型_C#_Razor Pages_Asp.net Core 3.0 - Fatal编程技术网

C# 添加在运行时可用于Razor页面的程序集/类型

C# 添加在运行时可用于Razor页面的程序集/类型,c#,razor-pages,asp.net-core-3.0,C#,Razor Pages,Asp.net Core 3.0,我正在尝试构建一个动态Web界面,在该界面中,我可以动态地指向一个文件夹,并使用ASP.NET核心从该文件夹中提供Web内容。通过使用ASP.NET Core中的文件提供程序来重新路由Web根文件夹,这非常容易。这适用于静态文件和RazorPages 然而,对于RazorPages来说,问题是一旦您这样做了,就不能为其他类型动态添加引用。我希望能够有选择地添加一个文件夹(PrivateBin),在启动时我可以循环使用它,加载程序集,然后让这些程序集在Razor中可见 不幸的是,它无法工作,因为R

我正在尝试构建一个动态Web界面,在该界面中,我可以动态地指向一个文件夹,并使用ASP.NET核心从该文件夹中提供Web内容。通过使用ASP.NET Core中的文件提供程序来重新路由Web根文件夹,这非常容易。这适用于静态文件和RazorPages

然而,对于RazorPages来说,问题是一旦您这样做了,就不能为其他类型动态添加引用。我希望能够有选择地添加一个文件夹(PrivateBin),在启动时我可以循环使用它,加载程序集,然后让这些程序集在Razor中可见

不幸的是,它无法工作,因为Razor即使在使用运行时编译时也看不到加载的程序集

我在启动期间使用以下命令加载程序集。请注意,从中加载这些内容的文件夹不在默认ContentRoot或WebRoot中,而是在新的重定向WebRoot中

//WebRoot是用户选择的路径,在这里通过命令行--WebRoot c:\temp\web指定
私有void加载私有二进制程序集()
{
var binPath=Path.Combine(WebRoot,“PrivateBin”);
if(Directory.Exists(binPath))
{
var files=Directory.GetFiles(binPath);
foreach(文件中的var文件)
{
如果(!file.EndsWith(“.dll”,StringComparison.CurrentCultureIgnoreCase)&&
!file.EndsWith(“.exe”,StringComparison.InvariantCultureIgnoreCase))
继续;
尝试
{
var asm=AssemblyLoadContext.Default.LoadFromAssemblyPath(文件);
Console.WriteLine(“附加程序集:+文件”);
}
捕获(例外情况除外)
{
Console.WriteLine(“未能加载专用程序集:+文件”);
}
}
}
}
程序集加载到AssemblyLoadContext()中,我可以使用反射和
Type.GetType(“namespace.class,assembly”)
访问该类型

但是,当我尝试访问RazorPages中的类型时(即使启用了运行时编译),这些类型也不可用。我得到以下错误:

为了确保该类型确实可用,我检查了Razor内部是否可以执行以下操作:

@{
var md=Type.GetType(“Westwind.AspNetCore.Markdown.Markdown,Westwind.AspNetCore.Markdown”);
var mdText=md.InvokeMember(“Parse”,BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,null,
null,新对象[]{“**asdasd**”,false,false,false});
}
@mdText
这很好。因此程序集被加载,类型可以访问,但Razor似乎没有意识到这一点

因此,问题是:


是否可以在运行时加载程序集,并使它们在运行时编译时可供Razor使用,并像通常通过直接声明性访问使用类型一样使用它?

快速查看ASP.NET核心源代码可以发现:

所有Razor视图编译都从以下位置开始:

(……)

它使用: (……,参考文献:…)

它使用:

它使用:

//简化
var referencePaths=ApplicationPartManager.ApplicationParts
第()类
.SelectMany(=>u0.GetReferencePath())
它使用:

因此我们需要以某种方式注册我们自己的
ICompilationReferencesProvider
,这就是..

应用程序部件管理器 在搜索应用程序部件时,
ApplicationPartManager
会做一些事情:

  • 它搜索隐藏的程序集,读取以下属性:
  • [assembly:ApplicationPartAttribute(assemblyName:“…”)]//指定要添加为ApplicationPart的程序集
    [assembly:RelatedAssemblyAttribute(assemblyFileName:“…”)]//指定要作为MVC程序集发现机制的一部分加载的程序集。
    //plus`Assembly.GetEntryAssembly()`在后台自动添加。
    
  • 然后它循环遍历所有找到的程序集,并使用(assembly)()查找扩展
    ApplicationPartFactory
    的类型

  • 然后对所有找到的
    ApplicationPartFactory
    s调用方法
    GetApplicationParts(assembly)

  • 没有
    ApplicationPartFactory的所有程序集
    获取
    DefaultApplicationPartFactory
    ,该程序集在
    GetApplicationParts
    中返回
    新的程序集(程序集)

    公共抽象IEnumerable GetApplicationParts(汇编);
    
    GetApplicationPartFactory GetApplicationPartFactory搜索
    [assembly:ProvideApplicationPartFactory(typeof(SomeType))]
    然后使用
    SomeType
    作为工厂

    公共抽象类ApplicationPartFactory{
    公共抽象IEnumerable GetApplicationParts(组装);
    公共静态应用程序PartFactory GetApplicationPartFactory(程序集)
    {
    // ...
    var providedAttribute=assembly.GetCustomAttribute();
    if(provideAttribute==null)
    {
    返回DefaultApplicationPartFactory.Instance;//此函数将'assembly'注册为'new AssemblyPart(assembly)`
    }
    var type=providedAttribute.GetFactoryType();
    // ...
    return(ApplicationPartFactory)Activator.CreateInstance(类型);
    }
    }
    
    一个解决方案 这意味着我们可以创建并注册(使用
    ProvideApplicationPartFactoryAttribute
    )我们自己的
    ApplicationPartFactory
    ,它返回一个自定义
    ApplicationPart
    实现
    ICompilationReferenceProvider
    的实现,然后在
    GetReferencePaths
    中返回我们的引用

    [程序集:ProvideApplicationPartFactory(typeof(MyApplicationPartFactory))]
    命名空间WebApplication1{
    公共类MyApplicationPartFactory:ApplicationPartFactory{
    公共覆盖IEnumerable GetApplicationParts(Asse
    
    @page
    
    <pre>
        output: [
            @(
                new ClassLibrary1.Class1().Method1()
            )
        ]
    </pre>
    
        output: [ 
            Hallo, World!
        ]