ILSpy中baml转化为xaml的改进(二)

前一篇中,只是对单一文件保存,进行了改进。

但在反编译时,还要一个一个的处理。

面对海量的代码,更需要一个能将所有的保存的工具。磨刀不误砍柴工,再改进一下工具。


首先找到在:

ILSpy\Languages\CSharpLanguage.cs

中,存在一段被注掉的代码:

// TODO implement extension point
                                   // var decompiler = Baml.BamlResourceEntryNode.CreateBamlDecompilerInAppDomain(ref bamlDecompilerAppDomain, assembly.FileName);
                                    /*string xaml = null;
                                    try
                                    {
                                        xaml = decompiler.DecompileBaml(ms, assembly.FileName, new ConnectMethodDecompiler(assembly), new AssemblyResolver(assembly));
                                    }
                                    catch (System.Xaml.XamlXmlWriterException) { } // ignore XAML writer exceptions
                                    if (xaml != null)
                                    {
                                        File.WriteAllText(Path.Combine(options.SaveAsProjectDirectory, Path.ChangeExtension(fileName, ".xaml")), xaml);
                                        yield return Tuple.Create("Page", Path.ChangeExtension(fileName, ".xaml"));
                                        continue;
                                    }

但是,根据目前对ILSpy 了解,这段代码是用不了的。

可能当时写这段代码的编程人员,还是基于相对旧的ILSpy 的框架来思考的,当时可能ILSpy还没有使用MEF框架。

(目前来讲,是在解决公司交给的具体问题,不是来研究细节的,Managed Extensibility Framework,还没仔细看。

所以,如果你读到这,也不用担心会讲这个玩意。)


如果你曾经了解过C++或是其它的语言里的插件框架,MEF本意就是解决这种问题的。

大意如下:

主工程中,建一个基类,然后对于每一种情况,编写了一个派生类来实现这种工作。

比如在ILSpy 中,有许多种待反编译的文件类型,如C#文件,资源文件,以及属性文件等。

但是,如果有一种现在还不想做的文件,或者是为未来预留的文件需要反编译的,这样主框架,就需要为这种能力预留接口。

但是主框架又不希望对其体系有多大破坏,这样,自然就想到了插件的方式。


世界上的实现有许多,但原理却那么几个,

如果了解COM或是其它的C++的,或是java之类的语言的插件体系,我们知道,不论如何做,有几个条件,是无法改变的:

1。 有一个所有插件共同遵守的基类或是抽象的基类,也就是所谓统一的接口。目的是受控插件接入主框架后,受主框架调度。

2。 有一套动态库加载的机制,如在win32中是loadlibrary之类的函数。

3。 有一个所有插件共同尊守的工厂函数,要说插件,com体系是比较严谨的。但COM一个最大的缺点就是与注册表依赖太大,使得一个系统中,不能有独立存在的插件,比较糟糕。而更加成功的插件,都是把DLL放在主程序身边。微软每次创新,都会搞一些退步的东西出来。

4。主框架不需要对插件形成静态依赖。


ok了,看到这,第一条,和第四条,是对我们当前的情况是有意义的。

再回头,看那段被注掉的代码,里面有一个类:

BamlResourceEntryNode
要知道,这个类在ILSpy.BamlDecompiler,这个插件中。

不用看代码我们知道,因为第四条,只能ILSpy.BamlDecompiler依赖ILSpy,而不能反向依赖。

这样,我们不能用这个类。而只能用它的基类ResourceEntryNode,或是基类接口 ILSpyTreeNode.


但老实说,这一段被注掉的代码,本质上就有问题。

因为从整个函数不清IEnumerable<Tuple<string, string>> WriteResourceFilesInProject(LoadedAssembly assembly, DecompilationOptions options, HashSet<string> directories)

来看,

作者的意思,是把界面和底层操作分开。主框架作者不想在这个函数中,用到与界面元素相关的东西。

但ResourceEntryNode是与树相关的。


但还是回到开始,是来解决我们自己的问题的,不是关心这些家伙怎么想,为达目的,有时完全会忘掉这些没用的东西。的确有许多程序员,一辈子就在框架中,没有为世界做什么贡献,结果是,一个十分钟能解决的问题,结果要一天才能掉定。所以,需要用到ResourceEntryNode。


好吧,但今天心情好,就按它的框架来试试吧。

先规划一下,要改哪些地方:

1。要生成指向ResourceEntryNode指针的BamlResourceEntryNode对象,显然,这里只能用ResourceEntryNode工厂里的Create函数。

2。 调用ResourceEntryNode里的一个可以被重载的函数,指向BamlResourceEntryNode里面的反编译函数,

3。 反编译的结果存盘。

当然,还有一个最重要的事情需要考虑,就是主框架与插件之间,如何传递数据和参数。

综合考虑,首先我们要找到那个override函数,在

 ILSpyTreeNode : SharpTreeNode 中,找到:

public abstract void Decompile(Language language, ITextOutput output, DecompilationOptions options);

就它了,然后开始工作:


1)ILSpy\Languages\CSharpLanguage.cs

								if (fileName.EndsWith(".baml", StringComparison.OrdinalIgnoreCase)) {
									MemoryStream ms = new MemoryStream();
									entryStream.CopyTo(ms);


                                    ICSharpCode.ILSpy.TreeNodes.ILSpyTreeNode node = ICSharpCode.ILSpy.TreeNodes.ResourceEntryNode.Create(fileName, ms);
                                    if (node != null)
                                    {
                                        string xaml=null;
                                        try
                                        {
                                            ICSharpCode.ILSpy.TextView.AvalonEditTextOutput output = new ICSharpCode.ILSpy.TextView.AvalonEditTextOutput();
                                            node.m_assembly = assembly;
                                            node.Decompile(this, output, options);
                                            xaml= output.GetDocument().Text;
                                           
                                        }
                                        catch (System.Xaml.XamlXmlWriterException) { } // ignore XAML writer exceptions
                                        catch (System.Exception ex)
                                        {
                                        	
                                        }
                                        if (xaml != null)
                                        {
                                            File.WriteAllText(Path.Combine(options.SaveAsProjectDirectory, Path.ChangeExtension(fileName, ".xaml")), xaml);
                                            yield return Tuple.Create("Page", Path.ChangeExtension(fileName, ".xaml"));
                                            continue;
                                        }
                                                                              
                                    }
2)ILSpy.BamlDecompiler\BamlResourceEntryNode.cs
        public override void Decompile(Language language, ICSharpCode.Decompiler.ITextOutput output, DecompilationOptions options)
        {
            //language.WriteCommentLine(output, string.Format("{0} = {1}", key, base.data));
            //AvalonEditTextOutput output = new AvalonEditTextOutput();
            if (LoadBaml_haoyujie((AvalonEditTextOutput)output))
            {
              //  output.
            }
        }

        bool LoadBaml_haoyujie(AvalonEditTextOutput output)
        {

			var asm = this.m_assembly;
			Data.Position = 0;
			XDocument xamlDocument = LoadIntoDocument(asm.GetAssemblyResolver(), asm.AssemblyDefinition, Data);
            curstr = xamlDocument.ToString();
			output.Write(curstr);
			return true;
		}
           

得承认,的确本人是比较懒的。

为了得到asm,直接改了基类,加了一个成员变量m_assembly:

	public abstract class ILSpyTreeNode : SharpTreeNode
	{
		FilterSettings filterSettings;
		bool childrenNeedFiltering;
        public LoadedAssembly m_assembly;   //haoyujie


}

好了,解决了。


另外,有处代码改了:

	public class ResourceEntryNode : ILSpyTreeNode
	{
		protected readonly string key;
		protected readonly Stream data;
        }

可执行文件

源码

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值