1

Resolved

Unable to load several versions of the toolkit into the same AppDomain

description

Hello,

We have a software which allows to add custom features by plugins. Plugins may add their own GUI with own panels, controls, etc. For different reasons it is essential that all plugins and the host software run in the same AppDomain. We recently got into the situation where two plugins used a different version of the WPF toolkit. In this scenario every time a panel was opened which contained a WPF toolkit control the software stopped working because of a missing resource. It turned out that the wrong version of the toolkit was used to resolve the resource.

After digging further into the issue we could locate the root cause in the merged resource dictionary in Main\Source\ExtendedWPFToolkitSolution\Src\Xceed.Wpf.Toolkit\Themes\Generic.xaml:

The merged resource dictionary doesn't specify a specific version for the other resource dictionaries. So the fix which worked for us is to change it from:
   <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="/Xceed.Wpf.Toolkit;component/Themes/Generic/Brushes.xaml" />
        <ResourceDictionary Source="/Xceed.Wpf.Toolkit;component/Themes/Generic/Buttons.xaml" />
...
   </ResourceDictionary.MergedDictionaries>
to:
   <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="/Xceed.Wpf.Toolkit;v1.9.0.0;component/Themes/Generic/Brushes.xaml" />
        <ResourceDictionary Source="/Xceed.Wpf.Toolkit;v1.9.0.0;component/Themes/Generic/Buttons.xaml" />
...
   </ResourceDictionary.MergedDictionaries>
This way the correct version of the resources will be resolved. The full solution would likely include a way to insert the current assembly version where I hard coded 1.9.0.0.

Would it be possible to add this fix to one of the next releases?

Best regards
Christian

file attachments

comments

emartin wrote Mar 6, 2013 at 2:16 PM

Thanks for your issue.
The solution some kind of anoying since it require some maintenance on every new version.
I've look why we just don't simply use relative path instead. Unfortunately theses does not seems to work inside Generic.xaml file.. I guess that I will have one more thing to do before each release...

References:
http://msdn.microsoft.com/en-us/library/aa970069.aspx
http://stackoverflow.com/questions/7772163/wpf-absolute-vs-relative-pack-uris
http://stackoverflow.com/questions/3730815/why-are-absolute-uris-required-for-merged-dictionaries-in-generic-xaml

chrilieb wrote Mar 6, 2013 at 5:55 PM

Thanks for your fast response.

I had hoped that there is a way in XAML to use the version in _XceedVersionInfo and insert that into the source string. Unfortunately I couldn't find a way to get that working especially because ResourceDictionary is not a dependency object (sometimes the small things are difficult in XAML).

Perhaps there is a way to create the resource dictionary from c# code like described here [1]. An alternative may be to edit the XAML file in a MSBuild step before the compilation takes place. I'm not sure if I like any of those two options. But I will think about it some more.

Here is a related issue which brought me to the solution posted in the issue description: [2].

Regards
Christian

[1] http://social.msdn.microsoft.com/Forums/is/wpf/thread/49018f5d-f802-426c-b2a0-b36df90b379d
[2] http://stackoverflow.com/questions/1453107/how-to-force-wpf-to-use-resource-uris-that-use-assembly-strong-name-argh

chrilieb wrote Mar 9, 2013 at 2:16 AM

Hi,

There might be a solution which is less annoying. Basically it's a subclass of ResourceDictionary which is responsible for adding the current version to the URI. I recognized that you have something similar already with XceedResourceDictionary, so you might want to implement the changes there. Here are some code snippets:
namespace Xceed.Wpf.Toolkit.Themes
{
    using System;
    using System.ComponentModel;
    using System.Windows;

    public class VersionSafeResourceDictionary : ResourceDictionary
    {
        private string _sourceComponent;

        public string SourceComponent
        {
            get
            {
                return _sourceComponent;
            }

            set
            {
                _sourceComponent = value;
                Source = new Uri(_XceedVersionInfo.GetFullResourceName(value), UriKind.Relative);
            }
        }
    }
}
I've added this method to _XceedVersionInfo:
        public static string GetFullResourceName(string path)
        {
            return "/Xceed.Wpf.Toolkit;v" + Version + ";" + path;
        }
And how to use it:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:themes="clr-namespace:Xceed.Wpf.Toolkit.Themes">
   <ResourceDictionary.MergedDictionaries>
        <themes:VersionSafeResourceDictionary SourceComponent="component/Themes/Generic/Brushes.xaml" />
...

emartin wrote Mar 11, 2013 at 1:51 PM

Thanks for your investigation. We will try to add it for the next version, but we have so many things to fix I cannot guarantee you it will be there...

chrilieb wrote Mar 18, 2013 at 4:47 PM

Although it would help us greatly if this issue would be resolved, it isn't urgent. So if you could fix it in the release after the next release, that would already be great.

BoucherS wrote Apr 15, 2013 at 4:13 PM

After some testing, the solution doesn't fix all problems.

When referencing the toolkit with a version in the MergeDictionaries of its Generic.xaml file, we will have the good objects from the tookit. But if those objects, in their Generic.xaml, are referencing others xaml files in their MergeDictionaries, they will also have to be referenced with a version.

There is also a problem when trying to access a toolkit element when defining "Keys" in xaml with "x:Static". It looks like the system is searching in the last version of the toolkit loaded (which is not always the good one).

Here's a sample showing the problem.

emartin wrote Apr 16, 2013 at 7:45 PM

Here is a new version of TestApp

chrilieb wrote Apr 19, 2013 at 1:05 PM

Thanks for looking into this and for pointing out these other scenarios which produce the same issue. Is there something where we can provide additional information or help to resolve the issue?

Christian

emartin wrote Apr 22, 2013 at 2:06 PM

The problem is that just adding the "VersionSafeResourceDictionary" to the Generic.xaml file won't make the Toolkit work properly.

Here what the issues we found:
1)
All "absolute" pack uri like <Image Source="/Xceed.Wpf.Toolkit;component/MyRes.png />in the resources files were also referring to the wrong assembly.

2)
Each places were a resource use a static reference to one of the assembly type or value to identify a key (ex. <Style x:Key="{x:Static tk:MyType.MyProp}" ... />) the result may end with the wrong value or a crash if the property doesn't exist in the "wrong" version of the toolkit.

However concerning the issue #1, this has been fixed by replacing all our references to relative uri.

For #2, We didn't had time to review and replace all theses usage with the "{ComponentResourceKey }" syntax that will probably fix the issue. It is not very long but since the tests has already been started this fix won't make the cut for v2.0. We will check this for v2.1.

chrilieb wrote Mar 10 at 8:35 AM

Thanks a lot for resolving this issue!