gpt4 book ai didi

c# - 动态加载程序集 - 设置和通信

转载 作者:太空宇宙 更新时间:2023-11-03 13:41:50 57 4
gpt4 key购买 nike

好吧...我有一个 WPF 应用程序(我们称它为 Launcher.exe),它加载并执行另一个 WPF 应用程序(我们称它为 Loaded.exe)动态地使用这样的东西:

Byte[] assemblyData;

using (BinaryReader reader = new BinaryReader(new FileStream(filePath, FileMode.Open)))
assemblyData = reader.ReadBytes(Convert.ToInt32(fs.Length));

Assembly assembly = Assembly.Load(assemblyData);
MethodInfo method = assembly.EntryPoint;

if (method != null)
{
Object instance = assembly.CreateInstance(method.Name);
method.Invoke(o, null);
}

现在...问题是 Launched.exe 在文件 Loaded.exe.config 中有自己的设置,它还在绑定(bind)中使用它们。例如:

Topmost="{Binding Mode=TwoWay, Path=Topmost, Source={x:Static p:Settings.Default}}"

第一个问题是,如何让我的动态加载程序集正确地加载/绑定(bind)/更新,更一般地说,使用它自己的设置?我不认为它可以自动处理这个...

第二个问题:Loaded.exe可以和Launcher.exe通信吗?比方说 Loaded.exe 需要一些只有 Launcher.exe 可以检索的数据...它如何请求它?我想我需要两个程序集之间的代理之类的东西,但我什至不知道如何开始编写代码...

最佳答案

我想您需要加载一个单独的程序集及其自己的 .config 文件,不是吗?我这样做的一种方法是将程序集加载到新的 AppDomain 中。您可以将该程序集部署在一个单独的文件夹中,其中包含他所有需要的引用。

首先设置AppDomain,这里有一个方法:

AppDomain getAppDomainForAssembly(string assemblypath, string appdomainname) 
{
//this._assembly_file = AssemblyFile;

string _assembly_file_name = System.IO.Path.GetFileName(assemblypath);
string _rootpath = System.IO.Path.GetDirectoryName(assemblypath);

//this._assembly_class_name = AssemblyClassNameToInstance;
AppDomainSetup _app_domain_info = new AppDomainSetup();
_app_domain_info.ApplicationBase = _rootpath;
_app_domain_info.PrivateBinPath = _rootpath;
_app_domain_info.PrivateBinPathProbe = _rootpath;
_app_domain_info.ConfigurationFile = _rootpath + @"\app.config"; //Here put the path to the correct .assembly .config file
AppDomain _app_domain = AppDomain.CreateDomain(
appdomainname, null, _app_domain_info);

return _app_domain;
}

然后获取在程序集上执行该方法的对象实例:

protected System.Reflection.Assembly _asm_resolve(string assemblyFile)
{
return System.Reflection.Assembly.LoadFrom(assemblyFile);
}

object getInstanceFromAppDomain(ref AppDomain appDomain,
string assemblyPath, string className = null)
{
if (string.IsNullOrEmpty(className))
{
System.Reflection.Assembly assembly = _asm_resolve(assemblyPath);
System.Reflection.MethodInfo method = assembly.EntryPoint;

return appDomain.CreateInstanceFromAndUnwrap(assemblyPath, method.Name);
}
else
{

return appDomain.CreateInstanceFromAndUnwrap(assemblyPath, className);

}
}

即使我们知道对象类型,我们也可以创建一个具有泛型类型的方法:

T getInstanceFromAppDomain<T>(ref AppDomain appDomain, 
string assemblyPath, string className = null)
{
if (string.IsNullOrEmpty(className))
{
System.Reflection.Assembly assembly = _asm_resolve(assemblyPath);
System.Reflection.MethodInfo method = assembly.EntryPoint;

return (T)appDomain.CreateInstanceFromAndUnwrap(assemblyPath, method.Name);
}
else
{

return (T)appDomain.CreateInstanceFromAndUnwrap(assemblyPath, className);

}
}

然后,在创建的实例上调用方法,该方法在新的 appDomain 中执行:

void executeMethod(Type objecttype, string methodname, ref object instancedObject, object[] methodparams) 
{
objecttype.InvokeMember(
methodname, System.Reflection.BindingFlags.InvokeMethod, null, instancedObject, methodparams);
}

你可以这样使用:

AppDomain newappdomain = getAppDomainForAssembly(filePath, "Loaded.exe.domain");
object loadedexe_object = getInstanceFromAppDomain(ref newappdomain,
filePath);

//If you know the method name to call...
executeMethod(loadedexe_object.GetType(), "methodname", ref loadedexe_object, null);

//or get entry point...
executeMethod(loadedexe_object.GetType(),
_asm_resolve(filePath).EntryPoint.Name, ref loadedexe_object, null);

对于第二个问题,您可以使用 NamedPipes、Remoting、WCF...您需要在同一台机器上实现进程间通信。查看 MSDN 文档,使用 WCF 涵盖此场景的代码示例 http://msdn.microsoft.com/en-us/library/system.servicemodel.netnamedpipebinding.aspx

请参阅 CodeProject 上的此示例,使用 Remoting Inter-process communication via Remoting

关于c# - 动态加载程序集 - 设置和通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16755882/

57 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com