我一直在尝试动态加载程序集到AppDomain.我需要这样做,因为我想动态调用一个方法,但是在我的应用程序运行时不要保留DLL的句柄,以便在需要时可以替换它.但是我收到了这个SerializationException异常:没有为成员"..."解析类型
这是我的代码:
AppDomain domain = AppDomain.CreateDomain("Temp AppDomain", null, AppDomain.CurrentDomain.SetupInformation);
try {
object obj = domain.CreateInstanceFromAndUnwrap(dllPath, typeName);
IMyInterface myObj = (IMyInterface) obj;
result = myObj.MyMethod(something);
}
finally {
AppDomain.Unload(domain);
}
Run Code Online (Sandbox Code Playgroud) 我在Visual Studio 2008中使用MSTEST.如何在某个测试类中使用每个单元测试方法,就好像它是第一个运行的测试,以便在运行每个测试之前重置所有全局状态?我不想使用TestInitialize,ClassInitialize,AssemblyInitialize等明确清理世界.例如:
[TestClass]
public class MyClassTests
{
[TestMethod]
public void Test1()
{
// The "Instance" property creates a new instance of "SomeSingleton"
// if it hasn't been created before.
var i1 = SomeSingleton.Instance;
...
}
[TestMethod]
public void Test2()
{
// When I select "Test1" and "Test2" to run, I'd like Test2
// to have a new AppDomain feel so that the static variable inside
// of "SomeSingleton" is reset (it was previously set in Test1) on
// the …Run Code Online (Sandbox Code Playgroud) 我必须调用一些写得不好的第三方COM组件,这些组件有内存泄漏,并且在长时间运行的过程中使用Single Threaded Apartment [STA].
我知道单独的进程将是实现它的好方法,我可以偶尔从长时间运行的进程重新启动它.
可以改用AppDomain吗?如果适当标记,AppDomain线程是否为STA线程?它是否有自己的COM对象内存?卸载AppDomain是否相当于杀死进程?
我正在构建一个多租户ASP .NET应用程序.鉴于每个租户可以动态配置他们的应用程序(可能涉及将动态自定义程序集加载到内存中),我需要一种隔离每个租户的方法.
出于维护原因,我不希望为每个租户创建一个新的Web应用程序.
我一直在考虑使用AppDomainManager为每个应用程序创建一个AppDomain,但似乎并不打算用于ASP .NET应用程序.
有没有人对这个问题有一些建议?
谢谢.
我一直在用C#开发Windows服务.
启动时,会为此服务提供一组配置文件路径.对于这些文件中的每一个,服务都将AppDomain使用该文件作为其ConfigurationFile文件的文件夹以及该文件的文件夹ApplicationBase.每个文件夹都有一个"bin"文件夹,设置为PrivateBinPath.
这些文件夹中的"bin"文件夹包含与服务共享的小型程序集,此程序集包含该接口IServiceHost.此外,IServiceHost已知实现接口的类的类型名称和程序集名称.
整个CreateServiceHost方法看起来像这样: -
public static IServiceHost CreateServiceHost(string configPath, string entryAssembly, string entryType)
{
IServiceHost host;
AppDomainSetup setupInfo = new AppDomainSetup();
setupInfo.ApplicationBase = Path.GetDirectoryName(configPath);
setupInfo.PrivateBinPath = Path.Combine(setupInfo.ApplicationBase, "bin");
setupInfo.ShadowCopyFiles = "true";
setupInfo.ConfigurationFile = configPath;
AppDomain appDomain = AppDomain.CreateDomain("Service for: " + setupInfo.ApplicationBase, AppDomain.CurrentDomain.Evidence, setupInfo);
object objHost = appDomain.CreateInstanceFromAndUnwrap(Path.Combine(setupInfo.PrivateBinPath, entryAssembly), entryType);
host = (IServiceHost)objHost;
return host;
}
Run Code Online (Sandbox Code Playgroud)
该IServiceHost界面是极其复杂的: -
public interface IServiceHost
{
void …Run Code Online (Sandbox Code Playgroud) 当在.NET中的AppDomains之间封送对象时,CLR将序列化对象(如果它具有该Serializable属性),或者它将生成代理(如果它继承自MarshalByRef)
但是对于字符串,CLR只会将对字符串对象的引用传递给新的AppDomain.CLR仍然确保完整性,因为.NET字符串是不可变的,并且第二个AppDomain对字符串的任何更改都不会影响原始对象.
这让我想到了一个问题:有没有办法告诉CLR我的自定义类型是不可变的,当用于远程处理它应该只是传递对象的引用,就像它对字符串类一样?
我编写了一小段关于动态加载程序集和从这些程序集创建类实例的代码,包括可执行文件,要动态加载的测试库和用于将动态程序集加载到新程序集的加载程序库Appdomain.Loader库由可执行文件和动态库引用.
//executable
[System.STAThreadAttribute()]
[System.LoaderOptimization(LoaderOptimization.MultiDomain)]
static void Main(string[] args)
{
AppDomainSetup domainSetup = new AppDomainSetup()
{
ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,
ApplicationName = AppDomain.CurrentDomain.SetupInformation.ApplicationName,
LoaderOptimization = LoaderOptimization.MultiDomain
};
AppDomain childDomain = AppDomain.CreateDomain("MyDomain", null, domainSetup);
Console.WriteLine(AppDomain.CurrentDomain.SetupInformation.LoaderOptimization.ToString());
Console.WriteLine(childDomain.SetupInformation.LoaderOptimization.ToString());
byte[] assembly = null;
string assemblyName = "CSTestLib";
using (FileStream fs = new FileStream(assemblyName+".dll",FileMode.Open))
{
byte[] byt = new byte[fs.Length];
fs.Read(byt,0,(int)fs.Length);
assembly = byt;
}
object[] pararmeters = {assemblyName,assembly};
string LoaderAssemblyName = typeof(AssemblyLoader).Assembly.FullName;
string LoaderClassName = typeof(AssemblyLoader).FullName;
AssemblyLoader assloader = (AssemblyLoader)childDomain.CreateInstanceAndUnwrap(LoaderAssemblyName,LoaderClassName , …Run Code Online (Sandbox Code Playgroud) 我有一个使用单独的C++ DLL的C#插件.对该DLL的唯一引用来自插件本身.父应用程序将所有插件加载到自己的AppDomain中,并在卸载插件时卸载此AppDomain.
我已经检查过,当我卸载插件时,我肯定会看到应用程序的内存丢失.我还能够删除所有已加载的托管程序集.问题是,当我尝试删除本机DLL时,我只是不断访问拒绝,直到我关闭整个应用程序.
我已经看了一段时间,但我仍然无法弄清楚为什么这个DLL留在内存中.
我正在尝试将来自不同程序集(在构建时不知道)的类型加载为"动态"并在该类型上执行方法.我的目标是完全断开'插件'与父应用程序的连接,这样就不需要任何共享代码或通用接口类型.通过加载类型上的预期方法签名来暗示接口.
这有效:
dynamic myObj = Assembly.Load("MyAssembly").CreateInstance("MyType");
myObj.Execute();
Run Code Online (Sandbox Code Playgroud)
但是,这会将类型加载到当前AppDomain及其所有依赖程序集.我想修改它以允许我在单独的AppDomain中执行相同的操作.
这有效,但没有使用dynamic关键字,我需要知道我实例化的显式类型,以便能够调用Execute方法:
var appDomain = AppDomain.CreateDomain(domainName, evidence, setup);
var myObj = appDomain.CreateInstanceAndUnwrap(assembly, type);
typeof(IMyInterface).InvokeMember("Execute", BindingFlags.InvokeMethod, null, myObj);
Run Code Online (Sandbox Code Playgroud)
这基本上是我的目标案例,我一直试图让这样的工作:
dynamic myObj = ad.CreateInstanceAndUnwrap(assembly, type);
myObj.Execute();
Run Code Online (Sandbox Code Playgroud)
我一直以RuntimeBinderException结束,消息"'System.MarshalByRefObject'不包含'Execute'的定义".这条消息有意义,确定它不包含'Execute'的定义,但我知道我实例化的类型确实包含'Execute'方法.我想这里有一些透明代理正在阻止它工作,但我不确定是什么.
我试图实例化的实际类看起来像这样:
[Serializable]
public class MyClass : MarshalByRefObject {
public void Execute() {
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
我也尝试过这个共享接口(不是我的主要目标,但我想先把它弄清楚)所以它看起来像:
[Serializable]
public class MyClass : MarshalByRefObject, IPlugin {
public void Execute() {
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
其中IPlugin是父应用程序中的已知类型,并且插件在构建时具有适当的引用,但这似乎也不起作用.
我猜这一点是不可能在AppDomain边界上加载一个动态类型.
有没有办法让它真正起作用?
我正在编写一个Asp.Net Core应用程序,该应用程序应该能够自行更新(在运行时替换自己的二进制文件).
这篇MSDN文章用经典的.Net框架描述了阴影复制,这正是我所需要的.但.Net Core中缺少整个AppDomain的东西.
所以我的问题是:
appdomain ×10
c# ×9
.net ×4
remoting ×2
.net-core ×1
asp.net ×1
asp.net-core ×1
auto-update ×1
clr ×1
dynamic ×1
mstest ×1
multi-tenant ×1
shadow-copy ×1
unit-testing ×1