AArnott / CodeGeneration.Roslyn

Assists in performing Roslyn-based code generation during a build.
Microsoft Public License
408 stars 59 forks source link

Generate from two (or more) sources, in different projects, output to third project #138

Closed MDLeide closed 5 years ago

MDLeide commented 5 years ago

My goal is to take input from 2 files in separate projects, and produce output to a third project.

I think there are several things preventing this currently, but wanted to make sure I'm not missing anything.

If it's not possible, I wonder if someone more familiar with the project might be able to make a broad guess at how difficult it would be to extend the project to support.

As a fallback option, is it possible to save generated code to a project different from the project owning the node which triggered the generation?

AArnott commented 5 years ago

This sounds like code generation based on what could be assemblies instead of projects. Is that right?

MDLeide commented 5 years ago

Perhaps assemblies would work... I hadn't thought along those lines. I've illustrated a contrived example below. Would I be able to achieve my goal by marking the Product.Extensions assembly, which references the two assemblies I'm actually interested in?

You may notice from this example that OrderData could be derived from Order, and thus, OrderExtensions could be derived directly from Order as well. However, I am trying to preserve hand-made changes to the OrderData class, and those changes may influence the final result.

// in assembly Product.Domain
// this is part of the source code
namespace Product.Domain.Orders
{
    public class Order
    {
        public int RowId { get; set; }
    }
}
// in assembly Product.Services.Contracts
// this is part of the source code
namespace Product.Services.Contracts.Orders
{
    [DataContract]
    public class OrderData
    {
        [DataMember]
        public int RowId { get; set; }
    }
}
// in assembly Product.Extensions
//      references Product.Domain
//      references Product.Services.Contracts
// this is the generated code
namespace Product
{
    public static class OrderExtensions
    {
        public static OrderData ToData(this Order order)
        {
            var data = new OrderData();
            data.RowId = order.RowId;
            return data;
        }

        public static Order ToDomain(this OrderData order)
        {
            var domain = new Order();
            domain.RowId = order.RowId;
            return domain;
        }
    }
}
amis92 commented 5 years ago

Depending on what you actually need to read:

  1. Compilation provides you with access to Symbol information in regards to all available types including those from referenced assemblies.

  2. I think extending #137 with a bit more work (extensible build of .rsp file) and passing Args to engines, you could read the projects needed however you want, and generate code based on that. It'd definitely be a very long task, as you'd probably need to read and compile both projects (again).