我不得不这样做几次,并且研究了许多不同的解决方案。
我发现最优雅,最容易实现的解决方案可以照此实现。
1.创建一个项目,您可以创建一个简单的界面
该界面将包含您要呼叫的任何成员的签名。
public interface IExampleProxy
{
string HelloWorld( string name );
}
保持该项目的清洁和轻便很重要。这是一个项目,双方都AppDomain
可以参考,并且将使我们不能参考该项目。Assembly
我们希望从客户端程序集中在单独域中加载的项目。
2.现在创建一个项目,其中包含您要单独加载的代码AppDomain
。
与客户端项目一样,该项目将引用代理项目,并且您将实现接口。
public interface Example : MarshalByRefObject, IExampleProxy
{
public string HelloWorld( string name )
{
return $"Hello '{ name }'";
}
}
3.接下来,在客户端项目中,将代码加载到另一个项目中AppDomain
。
因此,现在我们创建一个新的AppDomain
。可以指定程序集引用的基本位置。探测将检查GAC以及当前目录和AppDomain
基本位置中的依赖程序集。
// set up domain and create
AppDomainSetup domaininfo = new AppDomainSetup
{
ApplicationBase = System.Environment.CurrentDirectory
};
Evidence adevidence = AppDomain.CurrentDomain.Evidence;
AppDomain exampleDomain = AppDomain.CreateDomain("Example", adevidence, domaininfo);
// assembly ant data names
var assemblyName = "<AssemblyName>, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null|<keyIfSigned>";
var exampleTypeName = "Example";
// Optional - get a reflection only assembly type reference
var @type = Assembly.ReflectionOnlyLoad( assemblyName ).GetType( exampleTypeName );
// create a instance of the `Example` and assign to proxy type variable
IExampleProxy proxy= ( IExampleProxy )exampleDomain.CreateInstanceAndUnwrap( assemblyName, exampleTypeName );
// Optional - if you got a type ref
IExampleProxy proxy= ( IExampleProxy )exampleDomain.CreateInstanceAndUnwrap( @type.Assembly.Name, @type.Name );
// call any members you wish
var stringFromOtherAd = proxy.HelloWorld( "Tommy" );
// unload the `AppDomain`
AppDomain.Unload( exampleDomain );
如果需要,可以使用多种不同的方式加载装配体。您可以使用其他解决方案。如果您具有程序集限定名称,则我喜欢使用,CreateInstanceAndUnwrap
因为它会加载程序集字节,然后为您实例化您的类型并返回object
,您可以将其简单转换为代理类型,或者如果不将其转换为强类型代码,则可以使用动态语言运行库,并将返回的对象分配给dynamic
类型化的变量,然后直接在其上调用成员。
你有它。
这允许单独加载客户端项目未引用的程序集 AppDomain
并从客户端调用成员。
为了进行测试,我喜欢使用Visual Studio中的“模块”窗口。它将显示您的客户端程序集域以及该域中加载了哪些所有模块,以及新的应用程序域以及该域中加载了哪些程序集或模块。
关键是要确保您编码的代码是派生的MarshalByRefObject
或可序列化的。
“ MarshalByRefObject将允许您配置其所在域的生存期。例如,假设您要在20分钟内未调用代理的情况下破坏该域。
我希望这有帮助。