Assembly Reference Cleanup, How?

SyntaxEditor .NET Languages Add-on for WPF Forum

Posted 6 months ago by Robert Walker
Version: 18.1.0684
Avatar

In the 2018.1 documentation there is a typo:

Assembly Reference Cleanup

When an IProjectAssembly is no longer needed in your application, it is a good idea to its AssemblyReferences collection. When an assembly repository is used (described later in this topic), it will often track the reference count of an assembly. While that reference count remains above zero, it will track data for the assembly. When the reference count returns to zero, it will close up any open cache files or other resources that it may have open for the assembly.

Thus it is very important to clear the assembly references collection on a project assembly prior to the project assembly going out of scope, so that memory and resources for its referenced assemblies can be reclaimed when appropriate.

  1. I assume the word "cleanup" is missing?
  2. What is recommendation to remove an assembly reference? Use, e.g.,
    mCSharpProjectAssembly.AssemblyReferences.Remove
    ​
    The Remove wants an IProjectAssemblyReference object though. I'm having a difficult time navigating the object model from a string "assembly name" -> an IProjectAssemblyReference object.

Comments (12)

Posted 6 months ago by Robert Walker
Avatar

Oops not Robert, this is Scott :-)

Posted 6 months ago by Scott Jeslis
Avatar

This is Scott.

Posted 6 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Scott,

1) It should have read "clear" its AssemblyReferences collection.

2) Calling the Clear() method works to clear the entire collection.  If you want to remove a specific one, you can scan the collection to find the IProjectAssemblyReference item with the matching AssemblyName, then Remove() that one.

Thanks for letting us know about the typo.

[Modified 6 months ago]


Actipro Software Support

Posted 6 months ago by Scott Jeslis
Avatar

Thanks for the info but you forgot to answer the last part.

"Remove" in

mCSharpProjectAssembly.AssemblyReferences.Remove

expects a class object that implements the interface IProjectAssemblyReference.

What object that implements IProjectAssemblyReference can I use to call the Remove? I need to know how your AssemblyReferences.Add method takes a full name and creates a IProjectAssemblyReference from it.

See?

Posted 6 months ago by Scott Jeslis
Avatar

Nevermind, figured it out using C# and general collections coding.

Thanks!

Posted 6 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Scott,

I was saying you could walk the AssemblyReferences collection and each one of those has an AssemblyName property on it you could compare to an assembly string.  Then when you find a match, you could Remove() it.  

More specifically to your question though, there are multiple AssemblyReferences.Add method overloads and each constructs an IProjectAssemblyReference instance in a different way.  The class that implements IProjectAssemblyReference is internal.  But that shouldn't matter since all items in that AssemblyReferences implement the IProjectAssemblyReference interface.


Actipro Software Support

Posted 6 months ago by Scott Jeslis
Avatar

So performing the Remove() in real-time didn't completely work.

To start I try adding a new reference dynamically during runtime:

var projectReference = mCSharpProjectAssembly.AssemblyReferences.AddFrom(fullFilePathName);
if (projectReference != null)
{

The first time works like a charm, projectReference != null.

Then I remove it:

mCSharpProjectAssembly.AssemblyReferences.Remove(projectAssemblyReference);

If I try to readd the same reference again:

var projectReference = mCSharpProjectAssembly.AssemblyReferences.AddFrom(fullFilePathName);
if (projectReference != null)

Now I get projectReference == null

So how do I completely clean-up the reference dynamically without doing a Clear()?

Posted 6 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Scott,

It is likely in this scenario that .NET reflection is throwing an exception internally like:

System.IO.FileLoadException: 'API restriction: The assembly has already loaded from a different location. It cannot be loaded from a new location within the same appdomain.'

.NET reflection has issues with loading assemblies multiple times in the same AppDomain.  

We have an optional add-on that uses Microsoft's Roslyn API instead of reflection to load assemblies.  Roslyn doesn't have the issues that .NET reflection has with this, so it's able to load assemblies multiple times and in different locations.  The "SyntaxEditor / .NET Languages Add-on / Assemblies" topic in the documentation that comes with the controls talks about this a bit.  Look at the "Binary Assemblies" section  in that topic for details.


Actipro Software Support

Posted 6 months ago by Scott Jeslis
Avatar

Could be. but I'm trying to load it from the exact same location :-(

Posted 6 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Is the assembly the exact same, or a different version/build of the file in the same location?  At some point in the past we had started loading assemblies from paths with this logic when you call AssemblyReferences.AddFrom():

var bytes = File.ReadAllBytes(path);
assembly = Assembly.ReflectionOnlyLoad(bytes);

I believe that used to work around another reflection issue.  But now it doesn't seem to help with anything. 

If you are simply reloading an assembly that is exactly the same in the same location, you would be better served with the current API to do Assembly.LoadFrom(path) to get the Assembly object.  Then call AssemblyReferences.Add(assembly) instead.  


Actipro Software Support

Posted 6 months ago by Scott Jeslis
Avatar

Yes same exact DLL. I allow our users to add references dynamically from a dialog, similar to Visual Studio's "Add Reference". To make matters more challenging, I'm currently allowing multiple Syntax Editor instances using the same Assembly Reference Collection "cache".

I will look into using your suggestion.

Posted 6 months ago by Scott Jeslis
Avatar

Cool "Actipro Software Support person" :-D That last suggestion helped.

I did not try the Roslyn idea as we are still currently compiling against .NET 4.5.2 :-(

Thanks!

The latest build of this product (v2019.1 build 0686) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.