jeffkl / RoslynCodeTaskFactory

An MSBuild CodeTaskFactory that uses Roslyn compiler for cross platform compatibility
MIT License
26 stars 3 forks source link

For Type="Class", add reflection based property/ParameterGroup discovery support #33

Closed binki closed 6 years ago

binki commented 6 years ago

It would be very useful for me if I could declare a Task using the Class syntax and let the parameters be automatically discovered just as if my Task was declared in an assembly. I think that if I wrote my Task as an assembly, MSBuild would use reflection over the properties of my class to discover which properties are supported. This means that if I am overriding an existing Task to intercept/extend it, I would automatically inherit the properties it uses and can augment them with additional properties.

However, for CodeTaskFactory and RoslynCodeTaskFactory, currently the parameters must be explicitly provided via <ParameterGroup/>. This makes sense and is even required for Type="Fragment" and Type="Method". However, this is quite limiting for my use case of Type="Class".

My idea for the design of this would be to add a new parameter to the <Code/> element to enable this capability. Another option is to simply automatically do parameter discovery when <ParameterGroup/> is absent and Type="Class". Two hypothetical examples of these options:

Explicit AutomaticParameters="True":

<UsingTask
  TaskName="Csc"
  TaskFactory="CodeTaskFactory"
  AssemblyFile="$(RoslynCodeTaskFactory)"
  Condition=" '$(RoslynCodeTaskFactory)' != '' ">
  <Task>
    <Reference Include="$(RoslynTargetsPath)\Microsoft.Build.Tasks.CodeAnalysis.dll" />
    <Code Type="Class" Language="cs" AutomaticParameters="True">
      <![CDATA[
        public class Csc : Microsoft.CodeAnalysis.BuildTasks.Csc
        {
          public override bool Execute()
          {
            // Do something interceptive here…

            return base.Execute();
          }
        }
      ]]>
    </Code>
  </Task>
</UsingTask>

Implicit omission of <ParameterGroup/>:

<UsingTask
  TaskName="Csc"
  TaskFactory="CodeTaskFactory"
  AssemblyFile="$(RoslynCodeTaskFactory)"
  Condition=" '$(RoslynCodeTaskFactory)' != '' ">
  <Task>
    <Reference Include="$(RoslynTargetsPath)\Microsoft.Build.Tasks.CodeAnalysis.dll" />
    <Code Type="Class" Language="cs">
      <![CDATA[
        public class Csc : Microsoft.CodeAnalysis.BuildTasks.Csc
        {
          public override bool Execute()
          {
            // Do something interceptive here…

            return base.Execute();
          }
        }
      ]]>
    </Code>
  </Task>
</UsingTask>

I’m planning to try to implement this. Please let me know if you have any suggestions and if this functionality would be accepted into RoslynCodeTaskFactory.

binki commented 6 years ago

So far, it looks like RoslynCodeTaskFactory isn’t passed enough information by MSBuild to detect whether or not <ParameterGroup/> is present. Thus, it is impossible to implement the implicit option. For now, I’ll go with AutoDetectParameters="true" as the explicit opt-in.

jeffkl commented 6 years ago

Package will be available shortly

https://www.nuget.org/packages/RoslynCodeTaskFactory/2.0.7