A modern compile-time generated interception/proxy library
+
+
+
+
+
+
+
+
+
Avatar API
+
+
Main entry point API is Avatar.Of<T>, which creates an object that implements T:
+
+
ICalculatorcalculator=Avatar.Of<ICalculator>();
+
+// Extension methods to easily add behaviors without having
+// to cast to IAvatar
+calculator.AddBehavior((invocation,next)=>...);
+
+Console.WriteLine(calculator.Add(2,5));
+
+
+
There are overloads for implementing additional types, as well as passing constructor
+arguments if the base type T (which must be the first in the list, like in regular
+C# type declarations) is a class that provides a constructor with matching parameters:
+Avatar.Of<T, T1...Tn>(arg1, ... argn)
+
+
For anonymous behaviors, the delegate/lambda based overloads are typically sufficient.
+For more advanced or reusable behaviors, you can implement IAvatarBehavior instead.
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/api/index.md b/docs/api/index.md
new file mode 100644
index 0000000..5eff428
--- /dev/null
+++ b/docs/api/index.md
@@ -0,0 +1,21 @@
+# Avatar API
+
+Main entry point API is `Avatar.Of`, which creates an object that implements `T`:
+
+```csharp
+ICalculator calculator = Avatar.Of();
+
+// Extension methods to easily add behaviors without having
+// to cast to IAvatar
+calculator.AddBehavior((invocation, next) => ...);
+
+Console.WriteLine(calculator.Add(2, 5));
+```
+
+There are overloads for implementing additional types, as well as passing constructor
+arguments if the base type `T` (which must be the first in the list, like in regular
+C# type declarations) is a class that provides a constructor with matching parameters:
+`Avatar.Of(arg1, ... argn)`
+
+For anonymous behaviors, the delegate/lambda based overloads are typically sufficient.
+For more advanced or reusable behaviors, you can implement `IAvatarBehavior` instead.
diff --git a/docs/docfx.json b/docs/docfx.json
new file mode 100644
index 0000000..2b786cf
--- /dev/null
+++ b/docs/docfx.json
@@ -0,0 +1,54 @@
+{
+ "$schema": "http://json.schemastore.org/docfx",
+ "metadata": [
+ {
+ "src": [
+ {
+ "files": [ "*.cs" ],
+ "src": "../src/Avatar"
+ }
+ ],
+ "dest": "docs/api",
+ "filter": "filter.yml"
+ }
+ ],
+ "build": {
+ "content": [
+ {
+ "files": [
+ "*.yml",
+ "index.md"
+ ],
+ "src": "api",
+ "dest": "api"
+ },
+
+ {
+ "files": [
+ "*.md",
+ "toc.yml"
+ ]
+ }
+ ],
+ "resource": [
+ {
+ "files": [
+ "logo.svg",
+ "favicon.ico",
+ "favicon/*.*",
+ "assets/**/*.*"
+ ]
+ }
+ ],
+ "globalMetadata": {
+ "_appTitle": "Avatar",
+ "_rel": "/avatar/",
+ "_enableSearch": true
+ },
+ "template": [
+ "default",
+ "./template"
+ ],
+ "dest": "_site"
+ }
+}
diff --git a/docs/favicon.ico b/docs/favicon.ico
new file mode 100644
index 0000000..73e5200
Binary files /dev/null and b/docs/favicon.ico differ
diff --git a/docs/favicon/android-chrome-192x192.png b/docs/favicon/android-chrome-192x192.png
new file mode 100644
index 0000000..7e30979
Binary files /dev/null and b/docs/favicon/android-chrome-192x192.png differ
diff --git a/docs/favicon/android-chrome-512x512.png b/docs/favicon/android-chrome-512x512.png
new file mode 100644
index 0000000..30e192a
Binary files /dev/null and b/docs/favicon/android-chrome-512x512.png differ
diff --git a/docs/favicon/apple-touch-icon.png b/docs/favicon/apple-touch-icon.png
new file mode 100644
index 0000000..148927b
Binary files /dev/null and b/docs/favicon/apple-touch-icon.png differ
diff --git a/docs/favicon/favicon-16x16.png b/docs/favicon/favicon-16x16.png
new file mode 100644
index 0000000..4aa7669
Binary files /dev/null and b/docs/favicon/favicon-16x16.png differ
diff --git a/docs/favicon/favicon-32x32.png b/docs/favicon/favicon-32x32.png
new file mode 100644
index 0000000..6e271ee
Binary files /dev/null and b/docs/favicon/favicon-32x32.png differ
diff --git a/docs/favicon/site.webmanifest b/docs/favicon/site.webmanifest
new file mode 100644
index 0000000..76d20c5
--- /dev/null
+++ b/docs/favicon/site.webmanifest
@@ -0,0 +1,19 @@
+{
+ "name": "",
+ "short_name": "",
+ "icons": [
+ {
+ "src": "/favicon/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/favicon/android-chrome-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "theme_color": "#FFFFFF",
+ "background_color": "#FFFFFF",
+ "display": "standalone"
+ }
\ No newline at end of file
diff --git a/docs/filter.yml b/docs/filter.yml
new file mode 100644
index 0000000..7e10de5
--- /dev/null
+++ b/docs/filter.yml
@@ -0,0 +1,6 @@
+apiRules:
+ - exclude:
+ hasAttribute:
+ uid: System.ComponentModel.EditorBrowsableAttribute
+ ctorArguments:
+ - System.ComponentModel.EditorBrowsableState.Never
diff --git a/docs/images/AddInsertBehavior.png b/docs/images/AddInsertBehavior.png
new file mode 100644
index 0000000..501c33e
Binary files /dev/null and b/docs/images/AddInsertBehavior.png differ
diff --git a/docs/images/AvatarApi.png b/docs/images/AvatarApi.png
new file mode 100644
index 0000000..81b5b0b
Binary files /dev/null and b/docs/images/AvatarApi.png differ
diff --git a/docs/images/AvatarIncubation.png b/docs/images/AvatarIncubation.png
new file mode 100644
index 0000000..2a31a16
Binary files /dev/null and b/docs/images/AvatarIncubation.png differ
diff --git a/docs/images/DebuggerDisplay.png b/docs/images/DebuggerDisplay.png
new file mode 100644
index 0000000..ce0359a
Binary files /dev/null and b/docs/images/DebuggerDisplay.png differ
diff --git a/docs/images/DebuggingBehavior.png b/docs/images/DebuggingBehavior.png
new file mode 100644
index 0000000..839bcf8
Binary files /dev/null and b/docs/images/DebuggingBehavior.png differ
diff --git a/docs/images/icon-32.png b/docs/images/icon-32.png
new file mode 100644
index 0000000..64f669f
Binary files /dev/null and b/docs/images/icon-32.png differ
diff --git a/docs/images/icon.png b/docs/images/icon.png
new file mode 100644
index 0000000..53bc17d
Binary files /dev/null and b/docs/images/icon.png differ
diff --git a/docs/images/icon.svg b/docs/images/icon.svg
new file mode 100644
index 0000000..aed7833
--- /dev/null
+++ b/docs/images/icon.svg
@@ -0,0 +1,13 @@
+
\ No newline at end of file
diff --git a/docs/images/noun_alien_24531.svg b/docs/images/noun_alien_24531.svg
new file mode 100644
index 0000000..b58995a
--- /dev/null
+++ b/docs/images/noun_alien_24531.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/images/noun_alien_24531_100.png b/docs/images/noun_alien_24531_100.png
new file mode 100644
index 0000000..7a89df1
Binary files /dev/null and b/docs/images/noun_alien_24531_100.png differ
diff --git a/docs/images/noun_alien_24531_1200.png b/docs/images/noun_alien_24531_1200.png
new file mode 100644
index 0000000..bc87a86
Binary files /dev/null and b/docs/images/noun_alien_24531_1200.png differ
diff --git a/docs/images/noun_alien_24531_128.png b/docs/images/noun_alien_24531_128.png
new file mode 100644
index 0000000..0ae9785
Binary files /dev/null and b/docs/images/noun_alien_24531_128.png differ
diff --git a/docs/images/noun_alien_24531_512.png b/docs/images/noun_alien_24531_512.png
new file mode 100644
index 0000000..4e8c8a9
Binary files /dev/null and b/docs/images/noun_alien_24531_512.png differ
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 0000000..bd5a6c3
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+avatar | A modern compile-time generated interception/proxy library
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
A modern compile-time generated interception/proxy library
+
+
+
+
+
+
+
+
+
Avatar
+
+
Avatar is a modern interception library which implements the proxy pattern and runs everywhere, even where run-time code generation (Reflection.Emit) is forbidden or limitted, like physical iOS devices and game consoles, through compile-time code generation. The proxy behavior is configured in code using what we call a behavior pipeline.
+
+
+
Avatars blend in with the Na’vi seamlessly, and you can control their behavior precisely by ‘driving’ them through a psionic link. Just like a proxy, with behavior driven through code.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
NOTE: Avatar provides a fairly low-level API with just the essential building blocks on top of which higher-level APIs can be built, such as the upcoming Moq vNext API.
+
+
+
Requirements
+
+
Avatar is a .NET Standard 2.0 library and runs on any runtime that supports that.
+
+
Compile-time proxy generation leverages Roslyn source generators and therefore requires C# 9.0, which at this time is included in Visual Studio 16.8 (preview or later) and the .NET 5.0 SDK (RC or later). Compile-time generated proxies support the broadest possible run-time platforms since they don’t require any Reflection.Emit, and also don’t pay that performance cost either.
+
+
Whenever compile-time proxy generation is not available, a fallback generation strategy is used instead, which leverages Castle DynamicProxy to provide the run-time code generation.
+
+
The client API for configuring proxy behaviors in either case is exactly the same.
+
+
+
NOTE: even though generated proxies is the main usage for Avatar, the API was designed so that you can also consume the behavior pipeline easily from hand-coded proxies too.
AddBehavior/InsertBehavior overloads allow granular control of the avatar’s behavior pipeline, which is basically a chain of responsibility that invokes all configured behaviors that apply to the current invocation. Individual behaviors can determine whether to short-circuit the call or call the next behavior in the chain.
+
+
+
+
Behaviors can also dynamically determine whether they apply to a given invocation by providing the optional appliesTo argument. In addition to the delegate-based overloads (called anonymous behaviors), you can also create behaviors by implementing the IAvatarBehavior interface:
Some commonly used behaviors that are generally useful are provided in the library and can be added to avatars as needed:
+
+
+
+
DefaultValueBehavior: sets default values for method return and out arguments. In addition to the built-in supported default values, additional default value factories can be registered for any type.
+
+
+
DefaultEqualityBehavior: implements the Object.Equals and Object.GetHashCode members just like System.Object implements them.
+
+
+
RecordingBehavior: simple behavior that keeps track of all invocations, for troubleshooting or reporting.
+
+
+
+
Customizing Avatar Creation
+
+
If you want to centrally configure all your avatars, the easiest way is to simply provide your own factory method (i.e. Stub.Of<T>), which in turn calls the Avatar.Of<T> provided. For example:
The [AvatarGenerator] attribute is required if you want to leverage the built-in compile-time code generation, since that signals to the source generator that calls to your API end up creating an avatar at run-time and therefore a generated type will be needed for it during compile-time. You can actually explore how this very same behavior is implemented in the built-in Avatar API which is provided as a content file:
As you can see, the Avatar API itself uses the same extensibility mechanism that your own custom factory methods can use.
+
+
Static vs Dynamic Avatars
+
+
Depending on the project and platform, Avatars will automatically choose whether to use run-time proxies or compile-time ones (powered by Roslyn source generators). The latter are only supported when building C# 9.0+ projects.
+
+
You can opt out of the static avatars by setting EnableCompiledAvatars=false in your project file:
This will switch the project to run-time proxies based on Castle.Core.
+
+
Debugging Optimizations
+
+
There is nothing more frustrating than a proxy you have carefully configured that doesn’t behave the way you expect it to. In order to make this a less frustrating experience, avatars are carefully optimized for debugger display and inspection, so that it’s clear what behaviors are configured, and invocations and results are displayed clearly and concisely. Here’s the debugging display of the RecordingBehavior that just keeps track of invocations and their return values for example:
+
+
+
+
And here’s the invocation debugger display from an anonymous behavior:
+
+
+
+
Samples
+
+
The samples folder in the repository contains a few interesting examples of how Avatar can be used to implement some fancy use cases. For example:
+
+
+
+
Forwarding calls to matching interface methods/properties (by signature) to a static class. The example uses this to wrap calls to System.Console via an IConsole interface.
+
+
+
Forwarding calls to a target object using the DLR (that backs the dynamic keyword in C#) API for high-performance late binding.
+
+
+
Custom Stub.Of<T> factory that creates avatars that have common behaviors configured automatically.
+
+
+
Custom avatar factory method that adds an int return value randomizer.
+
+
+
Configuring the built-in DefaultValueBehavior so that every time a string property is retrieved, it gets a random lorem ipsum value.
+
+
+
Logging all calls to an avatar to the Xunit output helper.
+
+
+
+
+
+
+
diff --git a/license.txt b/license.txt
new file mode 100644
index 0000000..83969dc
--- /dev/null
+++ b/license.txt
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) Daniel Cazzulino and Contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..a6bf9e8
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,144 @@
+
Avatar
+
+Avatar is a modern interception library which implements the [proxy pattern](https://en.wikipedia.org/wiki/Proxy_pattern) and runs everywhere, even where run-time code generation (Reflection.Emit) is forbidden or limitted, like physical iOS devices and game consoles, through compile-time code generation. The proxy behavior is configured in code using what we call a *behavior pipeline*.
+
+> *Avatars blend in with the Na'vi seamlessly, and you can control their behavior precisely by 'driving' them through a psionic link. Just like a [proxy](https://en.wikipedia.org/wiki/Proxy_pattern), with behavior driven through code.*
+
+
+
+[](https://www.nuget.org/packages/Avatar)
+[](https://www.nuget.org/packages/Avatar)
+[](https://github.com/devlooped/avatar/blob/main/LICENSE)
+[](https://discord.gg/AfGsdRa)
+[](https://github.com/devlooped/avatar)
+
+[](https://pkg.kzu.io/index.json)
+[](https://github.com/devlooped/avatar/actions?query=branch%3Amain+workflow%3Abuild+)
+
+
+> NOTE: Avatar provides a fairly low-level API with just the essential building blocks on top of which higher-level APIs can be built, such as the upcoming Moq vNext API.
+
+## Requirements
+
+Avatar is a .NET Standard 2.0 library and runs on any runtime that supports that.
+
+Compile-time proxy generation leverages [Roslyn source generators](https://github.com/dotnet/roslyn/blob/master/docs/features/source-generators.cookbook.md) and therefore requires C# 9.0, which at this time is included in Visual Studio 16.8 (preview or later) and the .NET 5.0 SDK (RC or later). Compile-time generated proxies support the broadest possible run-time platforms since they don't require any Reflection.Emit, and also don't pay that performance cost either.
+
+Whenever compile-time proxy generation is not available, a fallback generation strategy is used instead, which leverages [Castle DynamicProxy](https://github.com/castleproject/Core/blob/master/docs/dynamicproxy-introduction.md) to provide the run-time code generation.
+
+The client API for configuring proxy behaviors in either case is exactly the same.
+
+> NOTE: even though generated proxies is the main usage for Avatar, the API was designed so that you can also consume the behavior pipeline easily from hand-coded proxies too.
+
+## Usage
+
+```csharp
+ICalculator calc = Avatar.Of();
+
+calc.AddBehavior((invocation, next) => ...);
+```
+
+`AddBehavior`/`InsertBehavior` overloads allow granular control of the avatar's behavior pipeline, which is basically a [chain of responsibility](https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern) that invokes all configured behaviors that apply to the current invocation. Individual behaviors can determine whether to short-circuit the call or call the next behavior in the chain.
+
+
+
+Behaviors can also dynamically determine whether they apply to a given invocation by providing the optional `appliesTo` argument. In addition to the delegate-based overloads (called *anonymous behaviors*), you can also create behaviors by implementing the `IAvatarBehavior` interface:
+
+```csharp
+public interface IAvatarBehavior
+{
+ bool AppliesTo(IMethodInvocation invocation);
+ IMethodReturn Execute(IMethodInvocation invocation, ExecuteHandler next);
+}
+```
+
+## Common Behaviors
+
+Some commonly used behaviors that are generally useful are provided in the library and can be added to avatars as needed:
+
+* `DefaultValueBehavior`: sets default values for method return and *out* arguments. In addition to the built-in supported default values, additional default value factories can be registered for any type.
+
+* `DefaultEqualityBehavior`: implements the *Object.Equals* and *Object.GetHashCode* members just like *System.Object* implements them.
+
+* `RecordingBehavior`: simple behavior that keeps track of all invocations, for troubleshooting or reporting.
+
+## Customizing Avatar Creation
+
+If you want to centrally configure all your avatars, the easiest way is to simply provide your own factory method (i.e. `Stub.Of`), which in turn calls the `Avatar.Of` provided. For example:
+
+```csharp
+ public static class Stub
+ {
+ [AvatarGenerator]
+ public static T Of() => Avatar.Of()
+ .AddBehavior(new RecordingBehavior())
+ .AddBehavior(new DefaultEqualityBehavior())
+ .AddBehavior(new DefaultValueBehavior());
+ }
+```
+
+The `[AvatarGenerator]` attribute is required if you want to leverage the built-in compile-time code generation, since that signals to the source generator that calls to your API end up creating an avatar at run-time and therefore a generated type will be needed for it during compile-time. You can actually explore how this very same behavior is implemented in the built-in Avatar API which is provided as a content file:
+
+
+
+The `Avatar.cs` contains, for example:
+
+```csharp
+[AvatarGenerator]
+public static T Of(params object[] constructorArgs) => Create(constructorArgs);
+
+[AvatarGenerator]
+public static T Of(params object[] constructorArgs) => Create(constructorArgs, typeof(T1));
+```
+
+As you can see, the Avatar API itself uses the same extensibility mechanism that your own custom factory methods can use.
+
+### Static vs Dynamic Avatars
+
+Depending on the project and platform, Avatars will automatically choose whether to use run-time proxies or compile-time ones (powered by Roslyn source generators). The latter are only supported when building C# 9.0+ projects.
+
+You can opt out of the static avatars by setting `EnableCompiledAvatars=false` in your project file:
+
+```xml
+
+ false
+
+```
+
+This will switch the project to run-time proxies based on Castle.Core.
+
+## Debugging Optimizations
+
+There is nothing more frustrating than a proxy you have carefully configured that doesn't behave the way you expect it to. In order to make this a less frustrating experience, avatars are carefully optimized for debugger display and inspection, so that it's clear what behaviors are configured, and invocations and results are displayed clearly and concisely. Here's the debugging display of the `RecordingBehavior` that just keeps track of invocations and their return values for example:
+
+
+
+And here's the invocation debugger display from an anonymous behavior:
+
+
+
+## Samples
+
+The `samples` folder in the repository contains a few interesting examples of how *Avatar* can be used to implement some fancy use cases. For example:
+
+* Forwarding calls to matching interface methods/properties (by signature) to a static class. The example uses this to wrap calls to *System.Console* via an *IConsole* interface.
+
+* Forwarding calls to a target object using the DLR (that backs the *dynamic* keyword in C#) API for high-performance late binding.
+
+* Custom `Stub.Of` factory that creates avatars that have common behaviors configured automatically.
+
+* Custom avatar factory method that adds an int return value randomizer.
+
+* Configuring the built-in *DefaultValueBehavior* so that every time a string property is retrieved, it gets a random lorem ipsum value.
+
+* Logging all calls to an avatar to the Xunit output helper.
+
+
+
+## Sponsors
+
+