using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; namespace SourceGen { [Generator] public class ExampleSourceGenerator : ISourceGenerator { public void Execute(GeneratorExecutionContext context) { //Debugger.Launch(); var assemblies = context.Compilation.SourceModule.ReferencedAssemblySymbols.ToArray(); var flag = assemblies.Any(v => v.Name == "UnityEngine"); var types = assemblies.SelectMany(a => { try { var main = a.Identity.Name.Split('.').Aggregate(a.GlobalNamespace, (s, c) => s.GetNamespaceMembers().Single(m => m.Name.Equals(c))); return GetAllTypes(main); } catch { return Enumerable.Empty(); } }).ToArray(); types = types.Where(t => t.TypeKind == TypeKind.Interface && t.DeclaredAccessibility == Accessibility.Public) .Where(v => v.AllInterfaces.Any(d => d.Name == "IProtocol")).ToArray(); var code = @"#nullable disable using System; using System.Runtime.Serialization; namespace SourceGen { #content } "; var str = ""; foreach (var model in types) { str += "\n[DataContract]"; str += $"\npublic struct {model.Name}Data:{model.ContainingNamespace}.{model.Name}"; str += "\n{"; var i = 0; foreach (var member in model.GetMembers()) { if (member is IPropertySymbol p) { str += $"\n [DataMember(Order = {i})]"; str += $"\n public {p.Type} {p.Name}{{get;set;}}"; i++; } } str += "\n}"; } code = code.Replace("#content", str); context.AddSource("Structs.cs", SourceText.From(code, Encoding.UTF8)); } public void Initialize(GeneratorInitializationContext context) { //context.RegisterForSyntaxNotifications(() => new CustomSyntaxReceiver()); } private static IEnumerable GetAllTypes(INamespaceSymbol root) { foreach (var namespaceOrTypeSymbol in root.GetMembers()) { if (namespaceOrTypeSymbol is INamespaceSymbol @namespace) { foreach (var nested in GetAllTypes(@namespace)) yield return nested; } else if (namespaceOrTypeSymbol is ITypeSymbol type) yield return type; } } } internal class CustomSyntaxReceiver : ISyntaxReceiver { public List Models { get; } = new List(); public void OnVisitSyntaxNode(SyntaxNode syntaxNode) { //Debugger.Launch(); if (syntaxNode.ToString().Contains("IStation520")) { } return; if (syntaxNode is InterfaceDeclarationSyntax it) { if (it.BaseList.Types.Any(v => v.Type.ToString() == "IProtocol")) { Models.Add(it); } } } } public class myReceiver : SourceReferenceResolver { public override bool Equals(object other) { throw new System.NotImplementedException(); } public override int GetHashCode() { throw new System.NotImplementedException(); } public override string NormalizePath(string path, string baseFilePath) { throw new System.NotImplementedException(); } public override Stream OpenRead(string resolvedPath) { throw new System.NotImplementedException(); } public override string ResolveReference(string path, string baseFilePath) { throw new System.NotImplementedException(); } } }