C# 动态加载的程序集-设置和;沟通
好吧,那么。。。我有一个WPF应用程序(我们称之为C# 动态加载的程序集-设置和;沟通,c#,.net,reflection,.net-assembly,appdomain,C#,.net,Reflection,.net Assembly,Appdomain,好吧,那么。。。我有一个WPF应用程序(我们称之为Launcher.exe),它可以动态加载和执行另一个WPF应用程序(我们称之为Loaded.exe),如下所示: Byte[] assemblyData; using (BinaryReader reader = new BinaryReader(new FileStream(filePath, FileMode.Open))) assemblyData = reader.ReadBytes(Convert.ToInt32(fs.Le
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);
}
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);
现在。。。问题是Launched.exe
在文件Loaded.exe.config
中有自己的设置,并且在绑定中也使用它们。例如:
Topmost="{Binding Mode=TwoWay, Path=Topmost, Source={x:Static p:Settings.Default}}"
第一个问题是,如何使动态加载的程序集正确地加载/绑定/更新,更一般地说,如何使用它自己的设置?我不认为它能自动处理这个
第二个问题是:
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);
}
}
您可以这样使用:
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);
}
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);
对于第二个问题,您可以使用命名管道、远程处理、WCF。。。
您需要在同一台机器上实现进程间通信。
看一看MSDN文档,代码示例用WCF覆盖了这个场景
请参阅CodeProject上的此示例,使用远程处理
或一些样品