Blog Logo
TAGS

# PrivateProxy

[![GitHub Actions](https://github.com/Cysharp/PrivateProxy/workflows/Build-Debug/badge.svg)](https://github.com/Cysharp/PrivateProxy/actions) [![Releases](https://img.shields.io/github/release/Cysharp/PrivateProxy.svg)](https://github.com/Cysharp/PrivateProxy/releases) [![NuGet package](https://img.shields.io/nuget/v/PrivateProxy.svg)](https://nuget.org/packages/PrivateProxy) Source Generator and .NET 8 [UnsafeAccessor](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.unsafeaccessorattribute) based high-performance strongly-typed private accessor for unit testing and runtime. `[GeneratePrivateProxy(typeof(TargetType))]` generates accessor proxy. ```csharp using PrivateProxy; public class Sample { int _field1; int PrivateAdd(int x, int y) => x + y; } [GeneratePrivateProxy(typeof(Sample))] public partial struct SampleProxy; ``` ```csharp // Source Generator generate this type partial struct SampleProxy(Sample target) { [UnsafeAccessor(UnsafeAccessorKind.Field, Name = _field1)] static extern ref int ___field1__(Sample target); [UnsafeAccessor(UnsafeAccessorKind.Method, Name = PrivateAdd)] static extern int __PrivateAdd__(Sample target, int x, int y); public ref int _field1 => ref ___field1__(target); public int PrivateAdd(int x, int y) => __PrivateAdd__(target, x, y); } public static class SamplePrivateProxyExtensions { public static SampleProxy AsPrivateProxy(this Sample target) { return new SampleProxy(target); } } ``` ```csharp // You can access like this. var sample = new Sample(); sample.AsPrivateProxy()._field1 = 10; ``` Generated code is fully typed, you can access private filed via IntelliSense and when private field was changed, can check compiler error. ![image](https://github.com/Cysharp/MemoryPack/assets/46207/f6dd22e1-e82e-4acc-ba6e-8895c8c8734b) * No performance penalty, it can be used not only for unit testing but also for runtime * No runtime dependency(all codes are included in source generator) * Private accessors are strongly-typed * Supports both instance, static and fields, properties, methods * Supports `ref`, `out`, `in`, and `ref readonly` method parameters * Supports `readonly` field and property * Supports `ref` return * Supports mutable struct For example, this is the mutable struct and static, ref return sample. ```csharp using PrivateProxy; public struct MutableStructSample { int _counter; void Increment() => _counter++; // static and ref sample static ref int GetInstanceCounter(ref MutableStructSample sample) => ref sample._counter; } // use ref partial struct [GeneratePrivateProxy(typeof(MutableStructSample))] public ref partial struct MutableStructSampleProxy; ``` ```csharp var sample = new MutableStructSample(); var proxy = sample.AsPrivateProxy(); proxy.Increment(); proxy.Increment(); proxy.Increment(); // call private static method. ref var counter = ref MutableStructSampleProxy.GetInstanceCounter(ref sample); Console.WriteLine(counter); // 3 counter = 9999; Console.WriteLine(proxy._counter); // 9999 ```