维护对 Assembly 对象的引用以避免不必要的 Assembly.LoadFrom 调用是好还是坏主意?
在插件系统中,我实例化对象并根据一些具有某些标识符(只是一个字符串)的传入请求调用这些对象的方法。借助配置,此标识符确定要加载哪个程序集、要实例化此程序集中的哪个类以及要调用哪个方法。程序集被加载到单独的 AppDomain 中。这种情况发生在像这样创建的代理类中:
secondDomain.CreateInstanceFromAndUnwrap(Assembly.GetExecutingAssembly().CodeBase,
typeof(SecondDomainProxy).FullName) as SecondDamainProxy;
在 SecondDomainProxy 类中,我加载与上面提到的 identifier
相关的程序集:
string assemblyFileName = GetAssemblyFileNameFromConfig(identifier);
Assembly assembly = Assembly.LoadFrom(assemblyFileName);
// Instantiate and run something in assembly
问题:持有对此 Assembly 对象的引用是否有意义一旦程序集被加载?例如,使用字典......
Dictionary<string, Assembly> _assemblyDict;
并将上面的代码更改为:
Assembly assembly;
if (!_assemblyDict.TryGetValue(identifier, out assembly))
{
string assemblyFileName = GetAssemblyFileNameFromConfig(identifier);
assembly = Assembly.LoadFrom(assemblyFileName);
_assemblyDict[identifier] = assembly;
}
// Instantiate and run something in assembly
我知道程序集在第一次调用 Assembly.LoadFrom 之后永远加载,直到卸载 AppDomain。 (在我的例子中,第二个 AppDomain 的寿命与主应用程序的寿命一样长。)那么这是否意味着对 Assembly.LoadFrom 的第二次调用很便宜,与字典查找一样便宜或几乎一样便宜?或者不调用 assembly.LoadFrom 并使用保存的引用是否有缺点?
(我的感觉是,除非我有很高的性能要求,但我没有(大约每 15 秒一个请求),否则这并不重要。但我可能是错的。)
提前感谢您的反馈!
编辑:
Assembly
是一个“普通”.NET 类。我认为,如果我没有对该类的实例的任何引用,它就会被垃圾收集。但组件本身仍保持加载状态。因此,Assembly.LoadFrom
至少需要创建 Assembly 类的一个新实例,尽管第二次该实例创建可能基于已加载的程序集。
我想添加一个问题:为给定的程序集创建程序集对象是否需要一些大量的反射,因此总是昂贵的,无论程序集是否加载?
In a plugin system I instantiate objects and call methods of those objects based on some incoming requests which have some identifier (simply a string). With the help of a configuration this identifier determines which assembly to load, which class in this assembly to instantiate and which method to call. The assemblies are loaded into a separate AppDomain. This happens in a proxy class which is created like so:
secondDomain.CreateInstanceFromAndUnwrap(Assembly.GetExecutingAssembly().CodeBase,
typeof(SecondDomainProxy).FullName) as SecondDamainProxy;
In the class SecondDomainProxy I load the assembly which is related to the identifier
mentioned above:
string assemblyFileName = GetAssemblyFileNameFromConfig(identifier);
Assembly assembly = Assembly.LoadFrom(assemblyFileName);
// Instantiate and run something in assembly
Question: Does it make sense to hold a reference to this Assembly object once the assembly has been loaded? For instance with a Dictionary...
Dictionary<string, Assembly> _assemblyDict;
... and by changing the code above to:
Assembly assembly;
if (!_assemblyDict.TryGetValue(identifier, out assembly))
{
string assemblyFileName = GetAssemblyFileNameFromConfig(identifier);
assembly = Assembly.LoadFrom(assemblyFileName);
_assemblyDict[identifier] = assembly;
}
// Instantiate and run something in assembly
I am aware that the assembly is loaded after the first call of Assembly.LoadFrom forever until the AppDomain is unloaded. (The second AppDomain lives as long as the main application in my case.) So does that mean that a second call to Assembly.LoadFrom is cheap, as cheap or almost as cheap as the dictionary lookup? Or does it have drawbacks NOT to call assembly.LoadFrom and to use the saved reference instead?
(My feeling is that it doesn't really matter unless I have high performance requirements which I don't have (one request every 15 seconds roughly). But I could be wrong.)
Thank you for feedback in advance!
Edit:
Assembly
is a "normal" .NET class. If I don't have any references to an instance of this class it gets garbage collected, I think. But the assembly itself keeps still loaded. So Assembly.LoadFrom
needs at least to create a new instance of the Assembly class, although at the second time this instance creation might be based on the already loaded assembly.
I'd like to add the question: Does creating an assembly object for a given assembly require some heavy reflection and is therefore always expensive, no matter if the assembly is loaded or not?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不,没有必要。
加载到 AppDomain 后,可以使用底层 AppDomain 对象的 GetAssemblies() 方法来访问该程序集,该方法返回任何已加载/可用的程序集:http://msdn.microsoft.com/en-US/library/system.appdomain.getassemblies.aspx
卸载一个的唯一方法或多个程序集是通过使用同一类的静态 Unload() 方法来卸载 AppDomain。
No, it is not necessary.
Once loaded into an AppDomain, the assembly can accessed by using the GetAssemblies() method of the underlying AppDomain object that returns any loaded/available Assembly, s: http://msdn.microsoft.com/en-US/library/system.appdomain.getassemblies.aspx
The only way to unload one or more Assemblies is to unload the AppDomain, by using static Unload() method of the same class.