WPF - Use different Versions of DLLs with UserCont

2019-08-30 06:21发布

I have the Problem, when I have WPF UserControls and I have the DLL where this UserControl is located in different Versions loaded into the Assembly, the UserControl could not find it's Resources any more. (Maybe because they are there with the same Name but in different Versioned DLLs) Any know how to fix it?

3条回答
来,给爷笑一个
2楼-- · 2019-08-30 07:05

I found a way myself, by changeing the "IntializeComponent" Method in the DLL. This Builds a URI, wich then loades the XAML. The Problem is, in the URI, the Version is not included! So I created a small App, wich I call after the compile Process, wich modifies the DLL so that the Version String it's included! For this, it's using Mono.Cecil...

Here is the code:

class Program
{
    static void Main(string[] args)
    {            
        var path = Environment.CurrentDirectory;

        if (args != null && args.Count() > 0)
            path = args[0];

        var dlls = Directory.GetFiles(path, "*.dll");

        foreach (var dll in dlls)
        {
            bool dllChanged = false;

            var ver = AssemblyName.GetAssemblyName(dll).Version;
            var nm = AssemblyName.GetAssemblyName(dll).Name;
            var oldTxt = "/" + nm + ";";
            var newTxt = "/" + nm + ";v" + ver.ToString() + ";";

            var readerParameters = new ReaderParameters {ReadSymbols = true};
            var assemblyDefinition = AssemblyDefinition.ReadAssembly(dll, readerParameters);

            var methodDefinition =
                assemblyDefinition.MainModule.Types.SelectMany(x => x.Methods)
                    .Where(x => x.Name == "InitializeComponent");

            foreach (var def in methodDefinition)
            {
                for (int n = 0; n < def.Body.Instructions.Count; n++)
                {
                    var instr = def.Body.Instructions[n];

                    if (instr.OpCode == OpCodes.Ldstr && instr.Operand is string &&
                        ((string) instr.Operand).StartsWith(oldTxt))
                    {
                        var next = def.Body.Instructions[n + 1];

                        if (next.OpCode == OpCodes.Ldc_I4_2)
                        {
                            var op = ((string) instr.Operand);
                            op = op.Replace(oldTxt, newTxt);
                            instr.Operand = op;

                            dllChanged = true;
                        }
                    }
                }
            }

            if (dllChanged)
            {
                var writerParameters = new WriterParameters {WriteSymbols = true};
                assemblyDefinition.Write(dll, writerParameters);
            }
        }
    }
}
查看更多
SAY GOODBYE
3楼-- · 2019-08-30 07:11

Similar to this: https://stackoverflow.com/a/26689750/195275

But the answer does not require changing IL code. You can pass /p:AssemblyVersion to the msbuild.

查看更多
登录 后发表回答