public ReferenceChecker(CodeGenConfig config) { mCodeGenConfig = config; mWorkspace = MSBuildWorkspace.Create(); mWorkspace.LoadMetadataForReferencedProjects = true; mWorkspace.SkipUnrecognizedProjects = true; mProject = mWorkspace.OpenProjectAsync(mCodeGenConfig.Project).Result; if (mProject == null) { throw new ReferenceCheckerException("打开工程文件出错"); } mCompilation = mProject.GetCompilationAsync().Result as CSharpCompilation; if (mCompilation == null) { throw new ReferenceCheckerException("GetCompilationAsync failed"); } mReferenceStrArray = File.ReadAllLines(mCodeGenConfig.Cs2LuaReferenceFilePath); for (int i = 0; i < mReferenceStrArray.Length; i++) { if (mReferenceStrArray[i].StartsWith("CS.")) { mReferenceStrArray[i] = mReferenceStrArray[i].Replace("CS.", string.Empty); } } mLuaCallCSharpSymbol = mCompilation.GetTypeByMetadataName("XLua.LuaCallCSharpAttribute"); if (mLuaCallCSharpSymbol == null) { throw new ReferenceCheckerException("无法获取LuaCallCSharp符号,请确认工程已经导入xlua"); } }
public CodeGenImpl(CodeGenConfig config) { mCodeGenConfig = config; if (!File.Exists(mCodeGenConfig.Project)) { throw new CodeGenException("Solution文件不存在"); } mWorkspace = MSBuildWorkspace.Create(new Dictionary <string, string> { { "CheckForSystemRuntimeDependency", "true" } }); mWorkspace.LoadMetadataForReferencedProjects = true; mWorkspace.SkipUnrecognizedProjects = true; mProject = mWorkspace.OpenProjectAsync(mCodeGenConfig.Project).Result; if (mProject == null) { throw new CodeGenException("打开工程文件出错"); } else { Console.WriteLine("工程名:{0}", mProject.Name); } if (config.IsResolveReferenceManually) { Console.WriteLine("By手动解析引用"); mReferenceResolver = new ResolveReferenceByManual(); } else { Console.WriteLine("ByRosyln自动解析"); mReferenceResolver = new ResolveReferenceByRosyln(mProject); } mCompilation = mReferenceResolver.GetReferenceResolvedCompilation(config); if (mCompilation == null) { throw new CodeGenException("GetCompilationAsync failed"); } if (mCompilation.GetDiagnostics().Where((a) => a.Severity == DiagnosticSeverity.Error).Any()) { var diagnostis = mCompilation.GetDiagnostics().Where((a) => a.Severity == DiagnosticSeverity.Error).ToArray(); foreach (var item in diagnostis) { Console.WriteLine(item.ToString()); } throw new CodeGenException("存在编译错误"); } mLuaTableTypeSymbol = mCompilation.GetTypeByMetadataName("XLua.LuaTable"); if (mLuaTableTypeSymbol == null) { throw new CodeGenException("mLuaTableTypeSymbol empty"); } mSystemExceptionTypeSymbol = mCompilation.GetTypeByMetadataName("System.Exception"); if (mSystemExceptionTypeSymbol == null) { throw new CodeGenException("mSystemExceptionTypeSymbol empty"); } mLuaFunctionTypeSymbol = mCompilation.GetTypeByMetadataName("XLua.LuaFunction"); if (mLuaFunctionTypeSymbol == null) { throw new CodeGenException("mLuaFunctionTypeSymbol empty"); } mXLuaClassProxyAdapterTypeSymbol = mCompilation.GetTypeByMetadataName("XLuaClassProxyAdapter"); if (mXLuaClassProxyAdapterTypeSymbol == null) { throw new CodeGenException("mXLuaClassProxyAdapterTypeSymbol empty"); } }
CSharpCompilation IResolveReference.GetReferenceResolvedCompilation(CodeGenConfig config) { return(mProject.GetCompilationAsync().Result as CSharpCompilation); }
CSharpCompilation IResolveReference.GetReferenceResolvedCompilation(CodeGenConfig config) { string path = Path.GetDirectoryName(config.Project); string projFilePath = config.Project; string name = Path.GetFileNameWithoutExtension(projFilePath); string systemDllPath = config.SystemDllPath; List <string> preprocessors = new List <string>(); preprocessors.Add("__LUA__"); //存储引用refs List <MetadataReference> refs = new List <MetadataReference>(); List <string> files = new List <string>(); Dictionary <string, string> refByNames = new Dictionary <string, string>(); Dictionary <string, string> refByPaths = new Dictionary <string, string>(); //从csproj文件中解析XML获取引用 if (projFilePath.EndsWith(".csproj")) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(projFilePath); //查找ItemGroup下的Reference节点 var nodes = SelectNodes(xmlDoc, "ItemGroup", "Reference"); foreach (XmlElement node in nodes) { var aliasesNode = SelectSingleNode(node, "Aliases"); var pathNode = SelectSingleNode(node, "HintPath"); if (null != pathNode && !refByPaths.ContainsKey(pathNode.InnerText)) { if (null != aliasesNode) { refByPaths.Add(pathNode.InnerText, aliasesNode.InnerText); } else { refByPaths.Add(pathNode.InnerText, "global"); } } else { string val = node.GetAttribute("Include"); if (!string.IsNullOrEmpty(val) && !refByNames.ContainsKey(val)) { if (null != aliasesNode) { refByNames.Add(val, aliasesNode.InnerText); } else { refByNames.Add(val, "global"); } } } } string prjOutputDir = "bin/Debug/"; nodes = SelectNodes(xmlDoc, "PropertyGroup"); foreach (XmlElement node in nodes) { string condition = node.GetAttribute("Condition"); var defNode = SelectSingleNode(node, "DefineConstants"); var pathNode = SelectSingleNode(node, "OutputPath"); if (null != defNode && null != pathNode) { string text = defNode.InnerText.Trim(); if (condition.IndexOf("Debug") > 0 || condition.IndexOf("Release") < 0 && (text == "DEBUG" || text.IndexOf(";DEBUG;") > 0 || text.StartsWith("DEBUG;") || text.EndsWith(";DEBUG"))) { preprocessors.AddRange(text.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)); prjOutputDir = pathNode.InnerText.Trim(); break; } } } //查找ItemGroup下的ProjectReference节点 nodes = SelectNodes(xmlDoc, "ItemGroup", "ProjectReference"); foreach (XmlElement node in nodes) { string val = node.GetAttribute("Include"); string prjFile = Path.Combine(path, val.Trim()); var nameNode = SelectSingleNode(node, "Name"); if (null != prjFile && null != nameNode) { string prjName = nameNode.InnerText.Trim(); string prjOutputFile = ParseProjectOutputFile(prjFile, prjName); string fileName = Path.Combine(prjOutputDir, prjOutputFile); if (!refByPaths.ContainsKey(fileName)) { refByPaths.Add(fileName, "global"); } } } nodes = SelectNodes(xmlDoc, "ItemGroup", "Compile"); foreach (XmlElement node in nodes) { string val = node.GetAttribute("Include"); if (!string.IsNullOrEmpty(val) && val.EndsWith(".cs") && !files.Contains(val)) { files.Add(val); } } //确保常用的Assembly被引用 if (!refByNames.ContainsKey("mscorlib")) { refByNames.Add("mscorlib", "global"); } if (!refByNames.ContainsKey("System")) { refByNames.Add("System", "global"); } if (!refByNames.ContainsKey("System.Core")) { refByNames.Add("System.Core", "global"); } if (string.IsNullOrEmpty(systemDllPath))//默认 { //用反射添加具体的类名引用 foreach (var pair in refByNames) { #pragma warning disable 618 Assembly assembly = Assembly.LoadWithPartialName(pair.Key); #pragma warning restore 618 if (null != assembly) { var arr = System.Collections.Immutable.ImmutableArray.Create(pair.Value); Console.WriteLine(pair.Key); refs.Add(MetadataReference.CreateFromFile(assembly.Location, new MetadataReferenceProperties(MetadataImageKind.Assembly, arr))); } } } //需配置SystemDLLPath else { foreach (var pair in refByNames) { string file = Path.Combine(systemDllPath, pair.Key) + ".dll"; var arr = System.Collections.Immutable.ImmutableArray.Create(pair.Value); refs.Add(MetadataReference.CreateFromFile(file, new MetadataReferenceProperties(MetadataImageKind.Assembly, arr))); } } //从文件路径添加DLL引用 foreach (var pair in refByPaths) { string fullPath = Path.Combine(path, pair.Key); var arr = System.Collections.Immutable.ImmutableArray.Create(pair.Value); Console.WriteLine(fullPath); if (!File.Exists(fullPath)) { Console.WriteLine(fullPath + "is not exsit!"); continue; } refs.Add(MetadataReference.CreateFromFile(fullPath, new MetadataReferenceProperties(MetadataImageKind.Assembly, arr))); } //手动构造Complation对象 CSharpCompilationOptions compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); compilationOptions = compilationOptions.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default); CSharpCompilation compilation = CSharpCompilation.Create(name); compilation = compilation.WithOptions(compilationOptions); //手动添加Reference compilation = compilation.AddReferences(refs.ToArray()); //手动添加SyntaxTree foreach (string itemFile in files) { string filePath = Path.Combine(path, itemFile); string fileName = Path.GetFileNameWithoutExtension(filePath); if (!File.Exists(filePath)) { Console.WriteLine(filePath + "is not exsit!"); continue; } CSharpParseOptions options = new CSharpParseOptions(); options = options.WithPreprocessorSymbols(preprocessors); options = options.WithFeatures(new Dictionary <string, string> { { "IOperation", "true" } }); SyntaxTree tree = CSharpSyntaxTree.ParseText(File.ReadAllText(filePath), options, filePath); compilation = compilation.AddSyntaxTrees(tree); } return(compilation); } return(null); }