Reputation: 5886
I want to create multiple instances of a .xaml UserControl named view.xaml
, which resides in an assembly dir1\asm.dll
and dir2\asm.dll
whereas asm.dll
is the same assembly that only differs in its version number and the implementation of view.xaml.
I have the following setup:
public void TestCreation() {
Assembly asm = null;
asm = Assembly.LoadFile("dir1\asm.dll");
CreateView(asm); // works!
asm = Assembly.LoadFile("dir2\asm.dll");
CreateView(asm); // works!
asm = Assembly.LoadFile("dir1\asm.dll");
CreateView(asm); // FAILS!
}
public void CreateView(Assembly assembly)
{
Type type = assembly.GetTypes().First<Type>(t => t.Name.Equals("View"));
UserControl view = (UserControl)assembly.CreateInstance(type.FullName, false, BindingFlags.CreateInstance, null, new object[] { }, null, null);
}
I am getting the following Exception:
with the Exception detail
I was able to track the problem up to this location in the InitializeComponent() method of my view.xaml:
and more specificially within InitializeComponent():
Upvotes: 1
Views: 404
Reputation: 5886
After a week suffering and laboring with this issue, I finally found both the reason for the problem and its solution.
The problem lies within the auto-generated *.g.i.cs
file, which is called by the InitializeComponent()
method of a UserControl
, as seen by the following:
This file generates a string (a Resource Locator) that expresses the path to that xaml-component, as seen by the following:
Now, if you have multiple versions of the same assembly and both versions include the same xaml-file, WPF does not know what xaml-file to instantiate, because the Resource Locator only references the name of the assembly but not its version.
This results in a TargetInvocationException
, saying that
{"The component 'MyNamespace.MyUserControl' does not have a resource identified by the URI '/MyAssembly;comoponent/myusercontrol.xaml'"}
as follows:
The simple (but most definitely not obvious) solution for this is to add the version of the assembly to this Resource Locator. This can be achieved by modifying the build-file of the project by adding the <AssemblyVersion>
-tag as follows:
Credits for this go to:
Upvotes: 0
Reputation: 4322
Well, this was kind of fun...
Both assemblies have the same resource Uri. It would work if the Uri contained the version but VS doesn't seem to put that in there. Which ever one is loaded last (asm1 or asm2) seems to be able to use the non-versioned Uri without crashing.
If, instead of: "/ProblemEditor;component/problemeditor.xaml"
You had: "/ProblemEditor;v1.0.0.0;component/problemeditor.xaml" and "/ProblemEditor;v2.0.0.0;component/problemeditor.xaml"
Then there wouldn't be a problem.
What I did to recreate your environment was:
I then:
Then your code above works! works! WORKS!
I hope this an acceptable solution for you. If anyone else has a way around this without hacking dlls, I'd be interested to know as well.
Upvotes: 1