Here is a tweaked version of the quoted code from Matthieu that doesn't require knowing the namespace to extract the code. For WPF, put this in the application startup event code.
AppDomain.CurrentDomain.AssemblyResolve += (s, args) =>
{
// Note: Requires a using statement for System.Reflection and System.Diagnostics.
Assembly assembly = Assembly.GetExecutingAssembly();
List<string> embeddedResources = new List<string>(assembly.GetManifestResourceNames());
string assemblyName = new AssemblyName(args.Name).Name;
string fileName = string.Format("{0}.dll", assemblyName);
string resourceName = embeddedResources.Where(ern => ern.EndsWith(fileName)).FirstOrDefault();
if (!string.IsNullOrWhiteSpace(resourceName))
{
using (var stream = assembly.GetManifestResourceStream(resourceName))
{
Byte[] assemblyData = new Byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
var test = Assembly.Load(assemblyData);
string namespace_ = test.GetTypes().Where(t => t.Name == assemblyName).Select(t => t.Namespace).FirstOrDefault();
#if DEBUG
Debug.WriteLine(string.Format("\tNamespace for '{0}' is '{1}'", fileName, namespace_));
#endif
return Assembly.Load(assemblyData);
}
}
return null;
};
To make them available at compile time, I create a folder named ExternalDLLs and copy the dlls there and set them to EmbeddedResource as noted above. To use them in your code, you still need to set a reference to them, but set Copy local to False. To get the code to compile cleanly without errors you also need to set using statments in your code to the namespaces of the dlls.
Here is a little utility that spins through the embedded resource names and displays their namespaces in the output window.
private void getEmbeddedResourceNamespaces()
{
// Note: Requires a using statement for System.Reflection and System.Diagnostics.
Assembly assembly = Assembly.GetExecutingAssembly();
List<string> embeddedResourceNames = new List<string>(assembly.GetManifestResourceNames());
foreach (string resourceName in embeddedResourceNames)
{
using (var stream = assembly.GetManifestResourceStream(resourceName))
{
Byte[] assemblyData = new Byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
try
{
var test = Assembly.Load(assemblyData);
foreach (Type type in test.GetTypes())
{
Debug.WriteLine(string.Format("\tNamespace for '{0}' is '{1}'", type.Name, type.Namespace));
}
}
catch
{
}
}
}
}