我不得不这样做几次,并研究了许多不同的解决方案。
我发现的最优雅和最容易完成的解决方案可以这样实现。
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 中的 Modules 窗口。它将显示您的客户端程序集域以及该域中加载的所有模块以及您的新应用程序域以及该域中加载的程序集或模块。
关键是要确保您的代码是派生的MarshalByRefObject
或可序列化的。
`MarshalByRefObject 将允许您配置其所在域的生命周期。例如,假设您希望域在 20 分钟内未调用代理时销毁。
我希望这有帮助。