如何访问源生成器中项目引用的程序集?

2024-02-13

我有一个类库项目 First.csproj 和一个文件 ICar.cs:

namespace First
{
    public interface ICar
    {
        string Name { get; set; }
    }
}

我有一个空的类库项目 Second.csproj 和分析器(源生成器)项目 Second.Generator.csproj:

  1. 首先.csproj- 没有项目参考
  2. 第二个.csproj- 引用了 First.csproj 和 Second.Generator.csproj
  3. 第二个生成器.csproj- 没有项目参考

我想编写 Second.Generator.csproj MySourceGenerator.cs,它采用 Second.csproj,搜索其所有类库项目引用(本例中为 First.csproj)并实现其所有接口。结果应该是生成的代码:

namespace Second
{
    public class Car : First.ICar
    {
        public string Name { get; set; }
    }
}

问题是我无法访问源生成器中引用的项目。我尝试过使用反射:

namespace Second.Generator
{
    [Generator]
    public class MySourceGenerator : ISourceGenerator
    {
        public void Initialize(GeneratorInitializationContext context)
        {
        }

        public void Execute(GeneratorExecutionContext context)
        {
            var first = context.Compilation.References.First(); //this is First.dll

            var assembly = Assembly.LoadFrom(first.Display);
        }
    }
}

但我无法加载程序集:

无法加载文件或程序集 'file:///...First\bin\Debug\net6.0\ref\First.dll' 或 它的依赖项之一。不应加载参考程序集 执行。它们只能在仅反射加载器中加载 语境。

任何帮助将不胜感激。谢谢。


我已经找到了一些使用汇编符号的方法。使用反射并不是一个好主意。

namespace Second.Generator
{
    [Generator]
    public class MySourceGenerator : ISourceGenerator
    {
        public void Initialize(GeneratorInitializationContext context)
        {
        }

        public void Execute(GeneratorExecutionContext context)
        {
            var types = context.Compilation.SourceModule.ReferencedAssemblySymbols.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<ITypeSymbol>();
                }
            });

            var properties = types.Where(t => t.TypeKind == TypeKind.Interface && t.DeclaredAccessibility == Accessibility.Public).Select(t => new
            {
                Interface = t,
                Properties = t.GetMembers()
            });
        }

        private static IEnumerable<ITypeSymbol> 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;
            }
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何访问源生成器中项目引用的程序集? 的相关文章

随机推荐