我有一些代码循环遍历当前加载到在 ASP.NET 应用程序中运行的 AppDomain 中的类型。以下是我获取程序集的方法:
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
Run Code Online (Sandbox Code Playgroud)
当应用程序第一次启动时没有问题,并且我期望的所有类型都存在。但是,当我更新 Web.config 或终止 w3p.exe 进程(或该进程因任何原因被回收)时,只有一些我期望的类型可用。当我使用调试器单步执行时,我注意到私有搜索路径(我的应用程序的 bin 目录)中的某些程序集尚未加载。我假设所有程序集都在应用程序启动和重新启动时加载,无论是否立即需要它们。但在重新启动的情况下,除非这些程序集文件已更新,否则似乎不会发生这种情况。
我需要的是在启动时收集类型信息以供以后使用。但由于在重新启动期间类型不可用,因此当需要使用类型信息时会造成严重破坏。那么考虑到这一点,我该如何解决或解决这个缺陷呢?
Here's a small class I'm using to probe for a list of available plugins:
internal static class PluginDirectoryLoader
{
public static PluginInfo[] ListPlugins(string path)
{
var name = Path.GetFileName(path);
var setup = new AppDomainSetup
{
ApplicationBase = path,
ShadowCopyFiles = "true"
};
var appdomain = AppDomain.CreateDomain("PluginDirectoryLoader." + name, null, setup);
var exts = (IServerExtensionDiscovery)appdomain.CreateInstanceAndUnwrap("ServerX.Common", "ServerX.Common.ServerExtensionDiscovery");
PluginInfo[] plugins = null;
try
{
plugins = exts.ListPlugins(); // <-- BREAK HERE
}
catch
{
// to do
}
finally
{
AppDomain.Unload(appdomain);
}
return …Run Code Online (Sandbox Code Playgroud) 如何调用我在另一个 AppDomain 中创建的对象的方法?我想避免使用CreateInstanceFromAndUnwrap,因为这需要我引用我想要操作的 DLL。
public static void Main() {
// Create domain
AppDomain domain = AppDomain.CreateDomain("Foo");
// Load assembly
domain.Load("C:\\Foo.dll");
// Create instance of class
System.Runtime.Remoting.ObjectHandle inst
= domain.CreateInstance("C:\\Foo.dll", "MyNamespace.MyClass");
// Call method -- How can I do this ???
object result = inst.PleaseCallMethod("MyMethod", "param1", 42, "p3", null);
}
Run Code Online (Sandbox Code Playgroud)
我会Foo.dll:
namespace MyNamespace {
public class MyClass {
public string MyMethod(string p1, int p2, string p3, string p4) {
return "...";
}
}
}
Run Code Online (Sandbox Code Playgroud)
另外,如果不首先创建包含静态方法的(可能是静态的)类的实例,我将如何调用静态方法?
这是我关于堆栈溢出的第一个问题。我试图寻找一种解决方案,但在任何地方都找不到一个或类似的解决方案。
我有一个 MVC 网站项目,它有不同的 DLL(插件),由于这些 DLL 不需要部署在所有环境中,所以我从文件夹中的 Global.asax 中的 Application_Start 上动态加载它们,并仅部署每个环境所需的内容。所以我不知道在项目中引用它们,这样我就可以为所有人构建一个版本。
我的问题是 Type.GetType("FullClassName, AssemblyName") 总是在这些插件中的对象上返回 null。
在 Application_Start 上,我基本上加载一个程序集,将其注册到 GAC,将其加载到当前 AppDomain 中,初始化其元数据并使用反射运行其引导程序,以在全局 Unity 容器中注册组件。
foreach (string file in fileList) {
string fileName = (Path.GetFileName(file));
Assembly asm = Assembly.LoadFrom(file);
foreach (Type assemblyType in asm.GetTypes()) {
new System.EnterpriseServices.Internal.Publish().GacInstall(file);
AppDomain.CurrentDomain.Load(asm.GetName());
MetaDataHelper.InitialiseMetadataForAssembly(asm);
IBootstrapper bootsrapper = (IBootstrapper)Activator.CreateInstance(assemblyType, container);
bootsrapper.Initialise();
}
}
Run Code Online (Sandbox Code Playgroud)
我也尝试过这种方法,对我的程序集进行强命名并将它们添加到 web.config 中,但没有效果。
<dependentAssembly>
<assemblyIdentity name="MyAssembly" culture="neutral" publicKeyToken="123456789"/>
<codeBase version="1.0.1524.23149" href="FILE://C:/Myassemblies/MyAssembly2.dll"/>
</dependentAssembly>
Run Code Online (Sandbox Code Playgroud)
有人可以帮我吗我错过了什么吗?
提前致谢。
我正在创建一个自我更新的应用程序,我将大部分代码放在一个单独的DLL中.这是命令行,最终将在Mono上运行.我只是试图让这段代码在命令行的Windows上用C#工作.
如何创建ac#应用程序,我可以在运行时删除支持的dll?
AppDomain domain = AppDomain.CreateDomain("MyDomain");
ObjectHandle instance = domain.CreateInstance( "VersionUpdater.Core", "VersionUpdater.Core.VersionInfo");
object unwrap = instance.Unwrap();
Console.WriteLine(((ICommand)unwrap).Run());
AppDomain.Unload(domain);
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)
在ReadLine中,VersionUpdater.Core.dll仍然被锁定而无法删除
ICommand接口位于VersionUpdater.Common.dll中,由Commandline应用程序和VersionUpdater.Core.dll引用
我正在开发一个严重依赖插件的.net应用程序.应用程序本身包含与远程服务器的连接.
最近我深入研究了应用程序域,并将它们视为将插件代码与应用程序其余部分隔离开来的理想解决方案.
然而,有一个很大的缺点使我无法实现托管插件的应用程序域.似乎没有办法通过引用传递对象来传递对连接对象的引用所需的另一个应用程序域.
我希望有人可以给我一个解决方法,以便我可以传递对该对象的引用.
注意:创建代理是不可能的,连接层已经充当代理,因为类是自动生成的.
注意2:System.AddIn不能使用,因为它在紧凑的框架上不可用.
我有两个可执行文件引用相同的类库.在类库中,我有一个静态变量.这个静态变量如何在两个不同的可执行文件中持续存在?
这是它的样子:
public class MyClass
{
public static string MyVar;
}
Run Code Online (Sandbox Code Playgroud)
应用1:
public class MyApp1
{
public void SomeMethod()
{
MyClass.MyVar = "hello";
}
}
Run Code Online (Sandbox Code Playgroud)
应用2:
public class MyApp2
{
public void SomeOtherMethod()
{
if(MyClass.MyVar == "hello")
DoSomething();
}
}
Run Code Online (Sandbox Code Playgroud) 我通过C#执行.NET程序集时遇到了一些重大问题.我想从静态类调用静态方法(Main).我让它在当前域中工作,但显然我无法从那里卸载程序集.
首先,我尝试创建一个新的AppDomain:
AppDomain domain = AppDomain.CreateDomain("PluginDomain");
Run Code Online (Sandbox Code Playgroud)
由于我的主要问题是解析我正在尝试加载的程序集,我试图挂钩AssemblyResolve事件:
domain.AssemblyResolve += new ResolveEventHandler(this.OnAssemblyResolve);
Run Code Online (Sandbox Code Playgroud)
但是,我得到一个关于序列化的错误(即这个类).
我已成功加载一个汇编文件,它恰好位于BaseDirectory中,只需使用:
domain.Load("Assembly1");
Run Code Online (Sandbox Code Playgroud)
但有问题的程序集位于BaseDirectory的两个子目录中,即.BaseDirectory\dir1\dir2\Assembly2.dll - 当使用带有字符串程序集名称的domain.Load()(将PrivateBinPath安装到正确的子目录位置)时以及使用带有程序集字节的domain.Load()时,我得到FileNotFoundException (来自File.ReadAllBytes()).
我知道AppDomain.Load()已被删除,但它似乎是唯一可用的方法,考虑到我不想强制包含静态方法的类是非静态和可实例化的.
无论如何,我该怎么做才能确保汇编文件正确加载到新的AppDomain中?
我的主要目标是从程序集中动态执行一个方法,该方法可以调用我自己的程序,但必要时也必须完全卸载程序集.它的目的是成为一个插件系统.
当SslStream使用该Read(byte[] buffer, int offset, int count)方法正常阅读时,我得到了预期的结果.
但是,如果我将SslStream对象移动到一个新对象AppDomain,则读取仍然可以正常工作(即返回正确读取的字节数),但该buffer数组为空.
为什么是这样?
我需要从应用程序(Core.exe)读取标准输出,该输出在同一进程中运行但在不同的appDomain中运行.在处理流程时重定向输出很容易,但appDomains概念对我来说是新的.
所以..我开始在isolataed appDomain中应用程序
new HostedApp("core", "Core.exe").Run();
class HostedApp
{
internal string DomainName;
internal string AssemblyName;
internal AppDomain Ad;
internal Thread AppThrd;
public HostedApp(string a_domain, string a_assemblyName)
{
DomainName = a_domain;
AssemblyName = a_assemblyName;
Ad = AppDomain.CreateDomain(a_domain);
}
public void Run()
{
AppThrd = new Thread(RunApp);
AppThrd.Start();
}
private void RunApp()
{
try
{
Ad.ExecuteAssembly(AssemblyName);
}
catch(Exception _ex)
{
MessageBox.Show("Unhandled exception\n" + _ex);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我试图重定向当前进程的Console.Out,假设如果应用程序共享相同的进程,则会有单个标准输出.
但它只显示默认的appDomain标准输出.
所以,总结一下,我需要访问另一个appDomain应用程序标准输出.或者可能有一种方法从"核心"appDomain调用位于默认appDomain中的方法?
appdomain ×10
c# ×9
.net ×3
reflection ×2
assemblies ×1
attributes ×1
gettype ×1
marshalling ×1
mono ×1
remoting ×1
shadow-copy ×1
sslstream ×1
types ×1