且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

以编程方式添加参考

更新时间:2023-11-30 15:18:04

这不是在执行程序集中添加引用"之类的东西.您必须添加(加载)程序集本身.

您可以在编译过程中静态加载所有程序集,也可以在运行时加载并使用新程序集.这样,您就可以为系统开发插件:您可以从System.Reflection.Assembly中定位该类(不要按名称进行操作,这是不支持的;相反,声明并使用某个接口应该是一个插件类)使用System.Reflection.Assembly.GetTypes通过其接口实现并找到一个类,或者,您可以开发并使用一些Assembly属性来指出哪些类既可以用作插件实现类,又可以使用接口.)可以在安装过程中加载程序集使用方法System.Reflection.Assembly.LoadFileSystem.Reflection.Assembly.LoadFromSystem.Reflection.Assembly.Load运行时间.找到插件类后,获取并调用其构造函数,然后将构造的对象分配给接口引用.使用此接口引用可与此组件(在运行时动态加载)一起使用.

当您需要重复加载程序集时,可能会有一个更困难的要求.这将导致内存泄漏,因为–注意! —无法卸载组件.出于.NET意识形态的考虑,这样做是为了避免调用卸载代码时可能出现的问题.但是,可以通过在单独的应用程序域中加载新程序集来完成:可以卸载整个域.有关更多信息,请参见类System.AppDomain.可以使用System.AppDomain.Load方法将程序集加载到域中.
由于应用域之间完全的数据隔离,AppDomain方法可能需要大量的设计/开发方法,因此域间交换与进程间通信是相同的.对于域间通信,此任务得以简化,因为类System.AppDomain提供了简化的进程间通信工具,例如System.AppDomain.SetData方法.

据我所知,我已经列出了所有可能性.可以说System.Reflection.Emit方法也适用.这是事实,但超出了讨论的范围.发出方法可解决在运行时创建和使用代码的问题,而不使用已存在的已编译程序集.

—SA
This is no such thing as "adding reference" to executing assembly. You have to add (load) assembly itself.

You either load all assemblies statically during compilation or load and use a new assembly during run-time. This way you can develop plug-ins to your system: you can locate the class from System.Reflection.Assembly (don''t do it by name, this is unsupportable; instead, declare and use some interface a plug-in class is supposed to implement and find a class by its interface using System.Reflection.Assembly.GetTypes, alternatively, you can develop and use some assembly attribute to point out what classes to use as the plug-in implementation classes, but also use interface.) An assembly can be loaded during run time using the methods System.Reflection.Assembly.LoadFile, System.Reflection.Assembly.LoadFrom or System.Reflection.Assembly.Load. When a plug-in class is located, obtain and invoke its constructor and assign the constructed object to interface reference. Use this interface reference to work with this (dynamically loaded during run-time) assembly.

There can be a more difficult requirement, when you need to load assemblies repeatedly. This would cause a memory leak, because — attention! — it is not possible to unload assembly. This is designed so due to .NET ideology to avoid potential problems with calls to unloaded code. However, it can be done through loading a new assembly in a separate Application Domain: the whole domain can be unloaded. See the class System.AppDomain for more information. The assemblies can be loaded in the Domain using System.AppDomain.Load methods.

The AppDomain approach may need considerable design/development approach due to complete data isolation between Application Domains, so inter-domain exchange is the same inter-process communication. This task is simplified for inter-domain communications, because the class System.AppDomain provides simplified inter-process communication facilities such as System.AppDomain.SetData methods.

I''ve listed all of the possibilities, to best of my knowledge. One can say System.Reflection.Emit methods are also applicable. This is true but beyond the subject under discussion. Emits methods address creation and using of code during run time, not using already existing compiled assemblies.

—SA


//''这是创建运行时可执行文件并为其添加引用的非常小的示例.
公共静态void Main(string []争论)
{
System.Text.StringBuilder lScript = new System.Text.StringBuilder();
lScript.Append(公共类TestVB" + Environment.NewLine);
lScript.Append("Public Shared Sub Main()" + Environment.NewLine);
lScript.Append("System.Windows.Forms.MessageBox.Show(\" Hello World!\)" + Environment.NewLine);
lScript.Append("End Sub" + Environment.NewLine);
lScript.Append("End Class" + Environment.NewLine);
字符串tempPath = System.IO.Path.GetTempFileName();
System.IO.StreamWriter streamWriter = null;
streamWriter = System.IO.File.CreateText(tempPath);
streamWriter.Write(lScript.ToString());
streamWriter.Flush();
streamWriter.Close();
System.CodeDom.Compiler.CompilerResults comResult = null;
System.CodeDom.Compiler.CompilerErrorCollection compErrors =新的System.CodeDom.Compiler.CompilerErrorCollection();
Microsoft.VisualBasic.VBCodeProvider codeProvider =新的Microsoft.VisualBasic.VBCodeProvider();
System.CodeDom.Compiler.CompilerParameters编译器参数=新的System.CodeDom.Compiler.CompilerParameters();
editorParameters.ReferencedAssemblies.Add("System.dll");
editorParameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
editorParameters.GenerateExecutable = true;
editorParameters.TreatWarningsAsErrors = false;
comResult = codeProvider.CompileAssemblyFromFile(compilerParameters,tempPath);
compErrors = comResult.Errors;
System.Text.StringBuilder错误=新的System.Text.StringBuilder();
foreach(comResult.Errors中的System.CodeDom.Compiler.CompilerError comError)
{
errors.Append(comError.ToString());
}
Console.WriteLine(errors.ToString());
Console.ReadKey();
程序集myapplication = comResult.CompiledAssembly;
System.Diagnostics.ProcessStartInfo信息=新的System.Diagnostics.ProcessStartInfo(System.IO.Directory.GetParent(tempPath).FullName + @"\" + myapplication.ManifestModule.Name);
System.Diagnostics.Process.Start(info);
}
//''This is the very small sample of creating runtime executable and adding references to it.
public static void Main(string[] arguements)
{
System.Text.StringBuilder lScript = new System.Text.StringBuilder();
lScript.Append("Public Class TestVB" + Environment.NewLine);
lScript.Append("Public Shared Sub Main()" + Environment.NewLine);
lScript.Append("System.Windows.Forms.MessageBox.Show(\"Hello World!\")" + Environment.NewLine);
lScript.Append("End Sub" + Environment.NewLine);
lScript.Append("End Class" + Environment.NewLine);
string tempPath = System.IO.Path.GetTempFileName();
System.IO.StreamWriter streamWriter = null;
streamWriter = System.IO.File.CreateText(tempPath);
streamWriter.Write(lScript.ToString());
streamWriter.Flush();
streamWriter.Close();
System.CodeDom.Compiler.CompilerResults comResult = null;
System.CodeDom.Compiler.CompilerErrorCollection compErrors = new System.CodeDom.Compiler.CompilerErrorCollection();
Microsoft.VisualBasic.VBCodeProvider codeProvider = new Microsoft.VisualBasic.VBCodeProvider();
System.CodeDom.Compiler.CompilerParameters compilerParameters = new System.CodeDom.Compiler.CompilerParameters();
compilerParameters.ReferencedAssemblies.Add("System.dll");
compilerParameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
compilerParameters.GenerateExecutable = true;
compilerParameters.TreatWarningsAsErrors = false;
comResult = codeProvider.CompileAssemblyFromFile(compilerParameters, tempPath);
compErrors = comResult.Errors;
System.Text.StringBuilder errors = new System.Text.StringBuilder();
foreach (System.CodeDom.Compiler.CompilerError comError in comResult.Errors)
{
errors.Append(comError.ToString());
}
Console.WriteLine(errors.ToString());
Console.ReadKey();
Assembly myapplication = comResult.CompiledAssembly;
System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo(System.IO.Directory.GetParent(tempPath).FullName + @"\" + myapplication.ManifestModule.Name);
System.Diagnostics.Process.Start(info);
}