动态加载大会 - 设置 - 安培;通讯 [英] Dynamically Loaded Assembly - Settings & Communication
问题描述
好了,所以...我有一个WPF应用程序(我们称之为的Launcher.exe
),它加载并执行另一个WPF应用程序(我们称之为 Loaded.exe
)动态使用是这样的:
Ok so... I have a WPF application (let's call it Launcher.exe
) which loads and executes another WPF application (let's call it Loaded.exe
) dynamically using something like this:
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);
}
现在......问题是,启动。 exe文件
文件 Loaded.exe.config
中有自己的设置,它也使用它们绑定。例如:
Now... the problem is that Launched.exe
has its own settings in the file Loaded.exe.config
, and it also uses them in bindings. For example:
Topmost="{Binding Mode=TwoWay, Path=Topmost, Source={x:Static p:Settings.Default}}"
第一个问题是,如何才能让我的动态加载的程序集正确加载/绑定/更新和更普遍,利用自身的设置?我不认为它能够自动地处理这个问题...
First question is, how can I make my dynamically loaded assembly properly load/bind/update and, more generally, use its own settings? I don't think it can handle this automagically...
第二个问题是: Loaded.exe
沟通与的Launcher.exe
?比方说, Loaded.exe
需要一些数据,只有的Launcher.exe
可以检索...怎么还能要求什么呢?我想,我需要这样的东西两个组件之间的代理,但我甚至无法弄清楚如何开始编码这...
Second question is: can Loaded.exe
communicate with Launcher.exe
? Let's say Loaded.exe
needs some data that only Launcher.exe
can retrieve... how can it ask for it? I think I need something like a proxy between the two assemblies, but I can't even figure out how to start coding this...
推荐答案
我supose你需要加载一个单独的程序与它自己的config文件,不是吗?
的一种方式我这样做是加载程序集在一个新的AppDomain。你可能会与他所有需要的引用一个单独的文件夹部署组装
I supose you'll need to load a separate assembly with it's own .config file, no? One way i do that is to load the assembly in a new AppDomain. You'll could deploy that assembly in a separate folder with all his needed references.
先设定的AppDomain,在这里你有一个方法:
First setup the AppDomain, here you have a method:
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;
}
然后得到执行的组装方法的对象的实例:
Then get an instance of the object that executes the method on the assembly:
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);
}
}
即使我们知道对象类型我们可以创建一个泛型类型的方法:
Even if we know the Object Type, we could create a method with generic type:
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执行:
And then, invoke the method on the created instance, wich is executing in the new 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,远程处理,WCF ...
。您需要实现在同一台机器上的进程间通信。
看一看MSDN文件建立,占地此方案与WCF
的 http://msdn.microsoft.com/en-us/library/system.servicemodel.netnamedpipebinding.aspx
请参阅该样品在CodeProject上,使用远程
间通过Remoting
See this sample on CodeProject, using Remoting Inter-process communication via Remoting
这篇关于动态加载大会 - 设置 - 安培;通讯的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!