nuke
nuke copied to clipboard
Allow overridable component settings via ApplyX
Description
- Adapt
GetTarget
to supportInvocationExpression
(((configurator.Body as InvocationExpression).Expression as MemberExpression).Expression as ConstantExpression).Value
- Introduce new
ApplyX
method withExpression<Configure<T>>
(no overload, since ambiguous) - Add assertion in existing
Apply
method and check ifconfigurator.Target/Method
is declared by interface - Use
GetAllMembers
to get quasi-override for original member similar as inValueInjectionAttributeBase.GetMemberValue<T>
- Maybe base calls via
.Apply<T>(...)


Usage Example
interface ICompile : INukeBuild
{
Target Compile => _ => _
.Executes(() =>
{
var settings = new DotNetBuildSettings()
.ApplyX(x => x.CompileSettings);
});
Configure<DotNetBuildSettings> CompileSettings => _ => _;
}
interface ICompileWithSomething : INukeBuild
{
Configure<DotNetBuildSettings> ICompile.CompileSettings => _ => _
.SetProperty("foo", "bar");
}
class Build : ICompileWithSomething
{
}
With the help of @matkoch I managed to get this method working:
public static TSettings Apply<TComponent, TSettings>(this TSettings settings, Expression<Func<TComponent, Configure<TSettings>>> configurator)
{
var target = configurator.GetTarget();
var memberInfo = configurator.GetMemberInfo();
var config = memberInfo.GetValue<Configure<TSettings>>(target);
return config.Invoke(settings);
}
Which would have been called like this:
DotNetBuild(_ => _
.Apply(CompileSettingsBase)
.Apply((ICompileEx x) => CompileSettings));
Where ICompileX
looked like this:
public interface ICompileEx : ICompile
{
Configure<DotNetBuildSettings> ICompile.CompileSettings => _ =>
_.SetProperty("TestPropertyFromICompileEx.Key", "TestPropertyFromICompileEx.Value");
}
And Build
had this:
Configure<DotNetBuildSettings> ICompile.CompileSettings => _ => _.SetProperty("TestPropertyFromBuild.Key", "TestPropertyFromBuild.Value");
The end result was that only TestPropertyFromBuild
was present in the final settings and the ICompileX
"layer" was ignored (not called).
This is probably because they layers are not virtual.
Using GetValueNonVirtual
instead of GetValue
in the new Apply
method resulted in no layers being called at all.