VaettirNet.CodeGeneration.DelegateImplementation
0.0.5
dotnet add package VaettirNet.CodeGeneration.DelegateImplementation --version 0.0.5
NuGet\Install-Package VaettirNet.CodeGeneration.DelegateImplementation -Version 0.0.5
<PackageReference Include="VaettirNet.CodeGeneration.DelegateImplementation" Version="0.0.5" />
paket add VaettirNet.CodeGeneration.DelegateImplementation --version 0.0.5
#r "nuget: VaettirNet.CodeGeneration.DelegateImplementation, 0.0.5"
// Install VaettirNet.CodeGeneration.DelegateImplementation as a Cake Addin #addin nuget:?package=VaettirNet.CodeGeneration.DelegateImplementation&version=0.0.5 // Install VaettirNet.CodeGeneration.DelegateImplementation as a Cake Tool #tool nuget:?package=VaettirNet.CodeGeneration.DelegateImplementation&version=0.0.5
CodeGeneration.DelegateImplementation
Summary
A C# code generator that will generate delegating methods automatically for you that delegate implementations to a field (or fields for complex configurations).
There are often times when a class is wrapping some underlying implementation and only needs to slightly modify behavior (perhaps of only one or two methods), and having to manually write delegating methods can be cumbersome and error prone (accidentally copy/pasting the wrong inner call, for example).
System.IO.Stream is a particularly useful case, as there are dozens of methods that need to be overridden/implemented for optimal behavior.
Basic Usage
interface ISample { int GetValue(string input); }
partial class SampleClass : ISample {
[DelegateImplementation] private ISample _inner;
public SampleClass(ISample inner) => _inner = inner;
}
this will produce generated members that look something like the following
partial class SampleClass {
public int GetValue(string input) => _inner.GetValue(input);
}
Advanced Usage
Multiple fields
Delegation is performed for all types that the containing class and the field share in common, which means multiple delegations can be done by having fields with different overlapping types.
interface IFirst { int First(); }
interface ISecond { int Second(); }
partial class SampleClass : IFirst, ISecond {
[DelegateImplementation] private IFirst _first;
[DelegateImplementation] private ISecond _second;
}
Partial Implementations
If the implementing class already provides implementations for a particular method, that method will not be generated, and the provided implementation will be used.
Example
interface ISample {
int FirstMethod();
int SecondMethod();
}
partial class SampleClass : ISample {
[DelegateImplementation] private ISample _inner;
public int FirstMethod() => 7;
}
the generated class with only produce an implementation for SecondMethod
Specific types
Specific types can be passed to the attribute, which will cause it to only generate methods for that type and not others. This can be useful when delegating to multiple fields with overlapping types to specify which will be handled.
interface IFirst { int First(); }
interface ISecond : IFirst { int Second(); }
partial class SampleClass : IFirst, ISecond {
[DelegateImplementation] private IFirst _first;
[DelegateImplementation(typeof(ISecond))] private ISecond _second;
}
Without the specified type, this would produce an error,
because the IFirst
interface can be handled by multiple fields,
so it's necessary to mark _second
as only delegating the ISecond
implementation.
Explicit Implementations
Normally all implemented methods are implemented not explicitly (as public ...()
methods) except where necessary
(for example, when delegating IEnumerable<T>
there are conflicting GetEnumeator
methods, in which case
the generator attempts to generate the "best" method publicly, and the others explicitly.
However this behavior can be controlled with the ImplementExplicitly
argument.
interface ISample { int GetValue(string input); }
partial class SampleClass : ISample {
[DelegateImplementation(ImplementExplicitly = true)] private ISample _inner;
}
this will produce generated members that look something like the following
partial class SampleClass {
int ISample.GetValue(string input) => _inner.GetValue(input);
}
Implement Only Abstract / All Virtual
By default only the minimum number of methods are generated to get a correct implementation (so only abstract members of base classes and members of interfaces.
However this behavior can be controlled with the IncludeVirtual
argument.
abstract class SampleBase {
virtual int VirtGetValue(string input) => AbsGetValue() + 5;
abstract int AbsGetValue(string input);
}
partial class SampleClass : ISample {
[DelegateImplementation(IncludeVirtual = true)] private SampleBase _inner;
}
this will produce generated members that look something like the following
partial class SampleClass {
int ISample.GetValue(string input) => _inner.GetValue(input);
}
Without the IncludeVirtual
, only the AbsGetValue
method would get delegated.
With it true, it will generate VirtGetValue
as well.
However, it can be beneficial to also include all virtual members as well.
For example, System.IO.Stream has many virtual methods that are not necessary to override,
but if not overridden, the base implementations will perform very poorly (having to allocate temporary arrays and copying values in and out),
and it's preferable to also implement/delegate the virtual methods as well.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.