InterfaceFillerCodeGen 1.1.1-alpha
See the version list below for details.
dotnet add package InterfaceFillerCodeGen --version 1.1.1-alpha
NuGet\Install-Package InterfaceFillerCodeGen -Version 1.1.1-alpha
<PackageReference Include="InterfaceFillerCodeGen" Version="1.1.1-alpha" />
<PackageVersion Include="InterfaceFillerCodeGen" Version="1.1.1-alpha" />
<PackageReference Include="InterfaceFillerCodeGen" />
paket add InterfaceFillerCodeGen --version 1.1.1-alpha
#r "nuget: InterfaceFillerCodeGen, 1.1.1-alpha"
#:package InterfaceFillerCodeGen@1.1.1-alpha
#addin nuget:?package=InterfaceFillerCodeGen&version=1.1.1-alpha&prerelease
#tool nuget:?package=InterfaceFillerCodeGen&version=1.1.1-alpha&prerelease
InterfaceFiller - Explicit Aspect Oriented Programming (AOP) in C#
The most simple but full-feature AOP framework in .NET C# by:
- Minimal and concise. All junk code are:
- Two parameter-less attributes
string methodName
- Explicit. No reflection in hell.
- Flexible. wysiwyg
Within minutes reading, all magic is revealed by Find all References.
Table of content:
- 1. InterfaceFiller attribute
- 2. Wrapper attribute
- 3. Wrapper With Parameter
- 4. Wrapper Resolution
- 5. Wrapper (with parameter) for
Taskmethod - 6. Wrapper (with parameter) for
Task<TResult>method - 7. string methodName
- Void method
- Issue Report
Changelog
[1.1.0] - 2023-08-10
Added
1. [InterfaceFiller] attribute {#InterfaceFiller}
public interface ITestApi
{
int FunA(int x, int y);
Task<StreamContent> FunB(Barrier barrier, Random randomAccess);
}
The (must be) partial TestApi class, contains testApi backup field (ITestApi type).
public partial class TestApi : ITestApi
{
[InterfaceFiller]
private ITestApi testApi;
public TestApi(ITestApi testApi)
{
this.testApi = testApi;
}
}
TestApi has no implementation for interface ITestApi but no compiler error
because InterfaceFiller attribute marks to auto-generate the default implementation.
// <auto-generated />
partial class TestApi : ITestApi
{
public int FunA(int x, int y) => testApi.FunA(x, y);
public System.Threading.Tasks.Task<System.Net.Http.StreamContent> FunB(System.Threading.Barrier barrier, System.Random randomAccess) => testApi.FunB(barrier, randomAccess);
}
Note
- Class must be
partial - Class must have backup-field which field type is the interface type.
- Backup-field has
[InterfaceFiller]attribute. - If there is an implemention for a method, code-gen will skips for this method only.
<a id="Wrapper"></a>
2. Wrapper
'Aspect' your interface with custom behavior before and/or after execution.
2.1 Normal method
Given the interface
public interface ITestApi
{
int FunA(int x);
string FunB(int x, string y);
}
and the class
public partial class TestApi : ITestApi
{
[InterfaceFiller]
private ITestApi testApi;
public TestApi(ITestApi testApi)
{
this.testApi = testApi;
}
[Wrapper]
private T Wrapper<T>(Func<T> next)
{
// Logging code here...
var r = next();
// More logging code here...
return r;
}
}
It will generate the interface.
// <auto-generated />
partial class TestApi : ITestApi
{
public int FunA(int x)
{
Func<int> func = () => testApi.FunA(x);
return Wrapper(func);
}
public string FunB(int x, string y)
{
Func<string> func = () => testApi.FunB(x, y);
return Wrapper(func);
}
}
Wrapper method:
- Having
[Wrapper]attribute - Signature:
T Wrapper<T>(Func<T> next) - Must be Generic method
- The generic type must be method generic type
2.2 Task method
Given the interface
public interface ITestApi
{
Task FunA(int x);
Task FunB(int x, string y);
}
and the class
public partial class TestApi : ITestApi
{
[InterfaceFiller]
private ITestApi testApi;
public TestApi(ITestApi testApi)
{
this.testApi = testApi;
}
[Wrapper]
private async Task Wrapper(Func<Task> next)
{
// Logging code here...
await next();
// More Logging code here...
}
}
It will generate the interface implementation using back-up field and wapper method.
// <auto-generated />
partial class TestApi : ITestApi
{
public async System.Threading.Tasks.Task FunA(int x)
{
Func<System.Threading.Tasks.Task> func = () => testApi.FunA(x);
await Wrapper(func);
}
public async System.Threading.Tasks.Task FunB(int x, string y)
{
Func<System.Threading.Tasks.Task> func = () => testApi.FunB(x, y);
await Wrapper(func);
}
}
Wrapper for Task method:
- Having
[Wrapper]attribute - Signature:
async Task Wrapper(Func<Task> next)
2.3 Task<TResult> method
Given the interface
public interface ITestApi
{
Task<int> FunA(int x);
Task<string> FunB(int x, string y);
}
and the class
public partial class TestApi : ITestApi
{
[InterfaceFiller]
private ITestApi testApi;
public TestApi(ITestApi testApi)
{
this.testApi = testApi;
}
[Wrapper]
private async Task<T> Wrapper<T>(Func<Task<T>> next)
{
// Logging code here...
var r = await next();
// More Logging code here...
return r;
}
}
It will generate the interface implementation.
// <auto-generated />
partial class TestApi : ITestApi
{
public async System.Threading.Tasks.Task<int> FunA(int x)
{
Func<System.Threading.Tasks.Task<int>> func = () => testApi.FunA(x);
return await Wrapper(func);
}
public async System.Threading.Tasks.Task<string> FunB(int x, string y)
{
Func<System.Threading.Tasks.Task<string>> func = () => testApi.FunB(x, y);
return await Wrapper(func);
}
}
Wrapper method:
- Having
[Wrapper]attribute - Signature:
async Task<T> Wrapper<T>(Func<Task<T>> next) - Must be Generic method
- The generic type must be method generic type
<a id="WrapperWithParameter"></a>
3. Wrapper (with parameter)
3.1 Single param
Concern your 'Aspect' only.
Given the interface
public interface ITestApi
{
int FunA(int role);
string FunB(int role, string y);
}
and the class
public partial class TestApi : ITestApi
{
[InterfaceFiller]
private ITestApi testApi;
public TestApi(ITestApi testApi)
{
this.testApi = testApi;
}
[Wrapper]
private T Wrapper<T>(int role, Func<int, T> next)
{
// If role is VIP then call manager for permission
var r = next(role);
// More logging code here...
return r;
}
}
It will generate the interface implementation using back-up field and wapper method.
// <auto-generated />
partial class TestApi : ITestApi
{
public int FunA(int role)
{
Func<int, int> func = (__role) => testApi.FunA(__role);
return Wrapper(role, func);
}
public string FunB(int role, string y)
{
Func<int, string> func = (__role) => testApi.FunB(__role, y);
return Wrapper(role, func);
}
}
Wrapper method:
- Having
[Wrapper]attribute - Signature:
T Wrapper<T>(int role, Func<int, T> next)- All parameters before the last param (
Func<int, T> next) must be match exactly within parameters of each interface methods. If not, default implementation is used. E.g.int userRoleordouble rolewill not be match. - Last param signature
Func<int, T> next). - Input in last param
intmust match withint role
- All parameters before the last param (
- Must be Generic method
- The generic type must be method generic type
3.2 Too many param
Concern your 'Aspect' only.
Given the interface
public interface ITestApi
{
int FunA(int role);
string FunB(int role, string y);
}
and the class
public partial class TestApi : ITestApi
{
[InterfaceFiller]
private ITestApi testApi;
public TestApi(ITestApi testApi)
{
this.testApi = testApi;
}
[Wrapper]
private T Wrapper<T>(int role, string name, Func<int, string, T> next)
{
// If role is VIP then call manager for permission
var r = next(role, name);
// More logging code here...
return r;
}
}
It will generate the interface implementation using default not wrapper.
// <auto-generated />
partial class TestApi : ITestApi
{
public int FunA(int role)
=> testApi.FunA(role);
public string FunB(int role, string y)
=> testApi.FunB(role, y);
}
Wrapper method:
string nameparam in wrapper method match NO param in all interface methods.
<a id="WrapperResolution"></a>
4. Mutiple Wrapper (Wrapper resolution)
4.1 Exactly match
Given the interface
public interface ITestApi
{
int FunA(int role);
string FunB(int role, string y);
}
and the class
public partial class TestApi : ITestApi
{
[InterfaceFiller]
private ITestApi testApi;
public TestApi(ITestApi testApi)
{
this.testApi = testApi;
}
[Wrapper]
private T Wrapper1<T>(int role, Func<int, T> next)
{
// If role is VIP then call manager for permission
var r = next(role);
// More logging code here...
return r;
}
[Wrapper]
private T Wrapper2<T>(int role, string y, Func<int, string, T> next)
{
// If role is VIP then call manager for permission
var r = next(role, y);
// More logging code here...
return r;
}
}
It will generate the interface implementation.
Wrapper1→FunAWrapper2→FunB
// <auto-generated />
partial class TestApi : ITestApi
{
public int FunA(int role)
{
Func<int, int> func = (__role) => testApi.FunA(__role);
return Wrapper1(role, func);
}
public string FunB
(int role, string y)
{
Func<int, string, string> func = (__role, __y) => testApi.FunB(__role, __y);
return Wrapper2(role, y, func);
}
}
4.2 More params - higher precedence
Given the interface
public interface ITestApi
{
int FunA(int role, string name, DateTime dob, decimal amount);
}
and the class
public partial class TestApi : ITestApi
{
[InterfaceFiller]
private ITestApi testApi;
public TestApi(ITestApi testApi)
{
this.testApi = testApi;
}
[Wrapper]
private T Wrapper1<T>(int role, Func<int, T> next)
{
// If role is VIP then call manager for permission
var r = next(role);
// More logging code here...
return r;
}
[Wrapper]
private T Wrapper2<T>(int role, string name, Func<int, string, T> next)
{
// If role is VIP then call manager for permission
var r = next(role, name);
// More logging code here...
return r;
}
}
It will generate the interface implementation.
Wrapper2→FunAWrapper2is higher precedence because it covers more aspect (params) ofFunAthanWrapper1
// <auto-generated />
partial class TestApi : ITestApi
{
public int FunA(int role, string name, System.DateTime dob, decimal amount)
{
Func<int, string, int> func = (__role, __name) => testApi.FunA(__role, __name, dob, amount);
return Wrapper2(role, name, func);
}
}
4.2 Equal params - compile error
Given the interface
public interface ITestApi
{
int FunA(int role, string name, DateTime dob, decimal amount);
}
and the class
public partial class TestApi : ITestApi
{
[InterfaceFiller]
private ITestApi testApi;
public TestApi(ITestApi testApi)
{
this.testApi = testApi;
}
[Wrapper]
private T Wrapper1<T>(int role, string name, Func<int, string, T> next)
{
// If role is VIP then call manager for permission
var r = next(role, name);
// More logging code here...
return r;
}
[Wrapper]
private T Wrapper2<T>(int role, DateTime dob, Func<int, DateTime, T> next)
{
// If role is VIP then call manager for permission
var r = next(role, dob);
// More logging code here...
return r;
}
}
It will generate junk text to fail compiler
because both Wrapper1 and Wrapper2 cover equally 2 params of FunA
// <auto-generated />
partial class TestApi : ITestApi
{
mutipleWrapper
//Error: WrapperDoc.ITest.FunA(int, string, System.DateTime, decimal) has mutiple wrapper: WrapperDoc.Test.Wrapper1<T>(int, string, System.Func<int, string, T>), WrapperDoc.Test.Wrapper2<T>(int, System.DateTime, System.Func<int, System.DateTime, T>)
}
<a id="WrapperTask"></a>
5. Wrapper (with parameter) for Task method
Signature: async Task Wrapper(int a, Func<int, Task> next)
<a id="WrapperTaskTResult"></a>
6. Wrapper (with parameter) for Task<TResult> method
Signature: async Task<T> Wrapper<T>(int a, Func<int, Task<T>> next)
<a id="MethodName"></a>
7. string methodName
Add string methodName parameter after Func next to access the caller method name.
public interface ITestApi
{
int FunA(int role, string name, DateTime dob, decimal amount);
}
public partial class TestApi : ITestApi
{
[InterfaceFiller]
private ITestApi testApi;
public TestApi(ITestApi testApi)
{
this.testApi = testApi;
}
[Wrapper]
private T Wrapper1<T>(int role, string name, Func<int, string, T> next, string methodName)
{
// If role is VIP then call manager for permission
var r = next(role, name);
// More logging code here...
return r;
}
}
// <auto-generated />
partial class TestApi : ITestApi
{
public int FunA(int role, string name, System.DateTime dob, decimal amount)
{
Func<int, string, int> func = (__role, __name) => testApi.FunA(__role, __name, dob, amount);
return Wrapper1(role, name, func, "FunA");
}
}
7.1 Wrapper resolution:
string methodNamehas lower precedence than method param
public interface ITestApi
{
int FunA(int role, string name, DateTime dob, decimal amount);
}
public partial class TestApi : ITestApi
{
[InterfaceFiller]
private ITestApi testApi;
public TestApi(ITestApi testApi)
{
this.testApi = testApi;
}
[Wrapper]
private T Wrapper1<T>(int role, Func<int, T> next)
{
// If role is VIP then call manager for permission
var r = next(role);
// More logging code here...
return r;
}
[Wrapper]
private T Wrapper2<T>(Func<int, T> next, string methodName)
{
// If role is VIP then call manager for permission
var r = next(role, name);
// More logging code here...
return r;
}
}
// <auto-generated />
partial class TestApi : ITestApi
{
public int FunA(int role, string name, System.DateTime dob, decimal amount)
{
Func<int, int> func = (__role) => testApi.FunA(__role, name, dob, amount);
return Wrapper1(role, func, "FunA");
}
}
string methodNamewrapper is selected if method params precedence are equal.
public interface ITestApi
{
int FunA(int role, string name, DateTime dob, decimal amount);
}
public partial class TestApi : ITestApi
{
[InterfaceFiller]
private ITestApi testApi;
public TestApi(ITestApi testApi)
{
this.testApi = testApi;
}
[Wrapper]
private T Wrapper1<T>(int role, Func<int, T> next)
{
// If role is VIP then call manager for permission
var r = next(role);
// More logging code here...
return r;
}
[Wrapper]
private T Wrapper2<T>(string name, Func<string, T> next, string methodName)
{
// If role is VIP then call manager for permission
var r = next(name);
// More logging code here...
return r;
}
}
// <auto-generated />
partial class TestApi : ITestApi
{
public int FunA(int role, string name, System.DateTime dob, decimal amount)
{
Func<int, int> func = (__name) => testApi.FunA(role, __name, dob, amount);
return Wrapper2(name, func, "FunA");
}
}
<a id="Void"></a>
Void method
Void (Unsupport)
<a id="Issue"></a>
Issue Report
| 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. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.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
- InterfaceFillerCodeGenEngine (>= 1.1.1-alpha)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 5.0.0 | 236 | 3/23/2024 |
| 5.0.0-rc02 | 149 | 3/9/2024 |
| 5.0.0-rc01 | 149 | 3/9/2024 |
| 3.1.0 | 268 | 12/7/2023 |
| 3.1.0-rc03 | 163 | 12/5/2023 |
| 3.1.0-rc02 | 172 | 12/5/2023 |
| 3.1.0-rc01 | 167 | 12/4/2023 |
| 3.0.1-rc02 | 146 | 11/22/2023 |
| 3.0.1-rc01 | 125 | 11/22/2023 |
| 3.0.1-alpha01 | 157 | 11/16/2023 |
| 2.0.2-alpha02 | 194 | 8/30/2023 |
| 2.0.2-alpha01 | 185 | 8/28/2023 |
| 2.0.1 | 228 | 8/28/2023 |
| 2.0.0 | 217 | 8/28/2023 |
| 1.1.1-alpha | 209 | 8/11/2023 |
| 1.1.0 | 260 | 8/10/2023 |
| 1.0.9 | 259 | 7/16/2023 |
| 1.0.8 | 257 | 7/16/2023 |
| 1.0.7 | 252 | 6/16/2023 |
| 1.0.6 | 241 | 6/16/2023 |
| 1.0.5 | 242 | 6/4/2023 |
| 1.0.4 | 234 | 6/4/2023 |
| 1.0.3 | 239 | 6/4/2023 |
| 1.0.2 | 244 | 6/4/2023 |
| 1.0.1 | 231 | 6/4/2023 |
| 1.0.0 | 236 | 6/3/2023 |