Telerik blogs
As you may know you cannot use ILMerge to merge assemblies with XAML (WPF application) however there is a little known trick you can use to achieve your goal in a bit different way. 

- Add needed assemblies as embedded resources in your application
- Load needed assemblies from embedded resources in runtime

How to do this?

First you need to ensure that all referenced assemblies (except the framework itself) are added properly to the application resources on every application build. To do this you can use this simple MSBuild task (AfterResolveReferences) at the end of your project:

...
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Target Name="AfterResolveReferences">
    <ItemGroup>
      <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'">
        <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName>
      </EmbeddedResource>
    </ItemGroup>
  </Target>
...

Now you need to write some code to load needed assemblies from resources when requested. To do this you can define your own entry point for the WPF application, preload all assemblies from resources and return needed assembly using AppDomain.CurrentDomain.AssemblyResolve event:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
 
namespace WpfApplication1
{
    public class Program
    {
        [STAThreadAttribute]
        public static void Main()
        {
            var assemblies = new Dictionary<string, Assembly>();
            var executingAssembly = Assembly.GetExecutingAssembly();
            var resources = executingAssembly.GetManifestResourceNames().Where(n => n.EndsWith(".dll"));
 
            foreach (string resource in resources)
            {
                using (var stream = executingAssembly.GetManifestResourceStream(resource))
                {
                    if (stream == null)
                        continue;
 
                    var bytes = new byte[stream.Length];
                    stream.Read(bytes, 0, bytes.Length);
                    try
                    {
                        assemblies.Add(resource, Assembly.Load(bytes));
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.Print(string.Format("Failed to load: {0}, Exception: {1}", resource, ex.Message));
                    }
                }
            }
 
            AppDomain.CurrentDomain.AssemblyResolve += (s, e) =>
            {
                var assemblyName = new AssemblyName(e.Name);
 
                var path = string.Format("{0}.dll", assemblyName.Name);
 
                if (assemblies.ContainsKey(path))
                {
                    return assemblies[path];
                }
 
                return null;
            };
 
            App.Main();
        }
    }
}



That’s all! 

Enjoy!
Make your XAML development easier, visit Telerik XAMLFlix for more WPF tutorials and tips!

Download

WPF
About the Author

Vladimir Enchev

is Director of Engineering, Native Mobile UI & Frameworks

Related Posts

Comments

Comments are disabled in preview mode.