• This repository has been archived on 27/May/2024
  • Stars
    star
    239
  • Rank 168,763 (Top 4 %)
  • Language
    C#
  • License
    MIT License
  • Created about 1 year ago
  • Updated 6 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Source Generator and .NET 8 UnsafeAccessor based high-performance strongly-typed private accessor for unit testing and runtime.

PrivateProxy

GitHub Actions Releases NuGet package

Source Generator and .NET 8 UnsafeAccessor based high-performance strongly-typed private accessor for unit testing and runtime.

[GeneratePrivateProxy(typeof(TargetType))] generates accessor proxy.

using PrivateProxy;

public class Sample
{
    int _field1;
    int PrivateAdd(int x, int y) => x + y;
}

[GeneratePrivateProxy(typeof(Sample))]
public partial struct SampleProxy;
// 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);
    }
}
// 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

  • 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
  • Supports instance constructor

For example, this is the mutable struct and static, ref return, and constructor sample.

using PrivateProxy;

public struct MutableStructSample
{
    int _counter;
    void Increment() => _counter++;

    // static and ref sample
    static ref int GetInstanceCounter(ref MutableStructSample sample) => ref sample._counter;
    
    // constructor sample
    MutalbeStructSample(int x, int y) { /* ... */ }
}

// use ref partial struct
[GeneratePrivateProxy(typeof(MutableStructSample))]
public ref partial struct MutableStructSampleProxy;
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

// call private constructor and create instance.
var sample = MutableStructSampleProxy.CreateMutableStructFromConstructor(111, 222);

Installation

This library is distributed via NuGet, minimum requirement is .NET 8 and C# 12.

PM> Install-Package PrivateProxy

Package provides only analyzer and generated code does not dependent any other libraries.

Supported Members

GeneratePrivateProxy target type and member

public class/* struct */ SupportTarget
{
    // field
    private int field;
    private readonly int readOnlyField;
    
    // property
    private int Property { get; set; }
    private int GetOnlyProperty { get; }
    public int GetOnlyPrivateProperty { private get; set; }
    public int SetOnlyPrivateProperty { get; private set; }
    private int SetOnlyProperty { set => field = value; }
    private ref int RefGetOnlyProperty => ref field;
    private ref readonly int RefReadOnlyGetOnlyProperty => ref field;

    // method
    private void VoidMethod() { }
    private int ReturnMethod() => field;
    private int ParameterMethod(int x, int y) => x + y;
    private void RefOutInMethod(in int x, ref int y, out int z, ref readonly int xyz) { z = field; }
    private ref int RefReturnMethod() => ref field;
    private ref readonly int RefReadOnlyReturnMethod() => ref field;

    // static
    static int staticField;
    static readonly int staticReadOnlyField;
    static int StaticProperty { get; set; }
    static int StaticGetOnlyProperty { get; }
    public static int StaticGetOnlyPrivateProperty { private get; set; }
    public static int StaticSetOnlyPrivateProperty { get; private set; }
    private static int StaticSetOnlyProperty { set => staticField = value; }
    private static ref int StaticRefGetOnlyProperty => ref staticField;
    private static ref readonly int StaticRefReadOnlyGetOnlyProperty => ref staticField;
    private static void StaticVoidMethod() { }
    static int StaticReturnMethod() => staticField;
    static int StaticParameterMethod(int x, int y) => x + y;
    static void StaticRefOutInMethod(in int x, ref int y, out int z, ref readonly int xyz) { z = staticField; }
    static ref int StaticRefReturnMethod() => ref staticField;
    static ref readonly int StaticRefReadOnlyReturnMethod() => ref staticField;
    static ref int StaticRefReturnMethodParameter() => ref staticField;
    
    // constructor
    SupportTarget() { }
    SupportTarget(int x, int y) { }
}

Proxy type can be class => class or struct, struct => ref struct.

using PrivateProxy;

public class Sample;

// class proxy type both supports class and struct(recommend is struct)
[GeneratePrivateProxy(typeof(Sample))]
public partial class SampleProxy1;

[GeneratePrivateProxy(typeof(Sample))]
public partial struct SampleProxy2;

public struct SamplleStruct;

// struct only supports ref struct(when use standard struct, analyzer shows error)
[GeneratePrivateProxy(typeof(SamplleStruct))]
public ref partial struct SamplleStructProxy;

GeneratePrivateProxyAttribute has two constructor, when use PrivateProxyGenerateKinds parameter, can configure generate member kind.

public GeneratePrivateProxyAttribute(Type target) // use PrivateProxyGenerateKinds.All
public GeneratePrivateProxyAttribute(Type target, PrivateProxyGenerateKinds generateKinds)

[Flags]
internal enum PrivateProxyGenerateKinds
{
    All = 0, // Field | Method | Property | Instance | Static | Constructor
    Field = 1,
    Method = 2,
    Property = 4,
    Instance = 8,
    Static = 16,
    Constructor = 32,
}

Limitation

Currently, the following features are not supported

License

This library is licensed under the MIT License.

More Repositories

1

UniTask

Provides an efficient allocation free async/await integration for Unity.
C#
8,201
star
2

MagicOnion

Unified Realtime/API framework for .NET platform and Unity.
C#
3,838
star
3

MemoryPack

Zero encoding extreme performance binary serializer for C# and Unity.
C#
3,288
star
4

R3

The new future of dotnet/reactive and UniRx.
C#
2,177
star
5

ZString

Zero Allocation StringBuilder for .NET and Unity.
C#
2,060
star
6

ConsoleAppFramework

Zero Dependency, Zero Overhead, Zero Reflection, Zero Allocation, AOT Safe CLI Framework powered by C# Source Generator.
C#
1,635
star
7

MasterMemory

Embedded Typed Readonly In-Memory Document Database for .NET and Unity.
C#
1,521
star
8

MessagePipe

High performance in-memory/distributed messaging pipeline for .NET and Unity.
C#
1,406
star
9

Ulid

Fast .NET C# Implementation of ULID for .NET and Unity.
C#
1,314
star
10

ZLogger

Zero Allocation Text/Structured Logger for .NET with StringInterpolation and Source Generator, built on top of a Microsoft.Extensions.Logging.
C#
1,262
star
11

SimdLinq

Drop-in replacement of LINQ aggregation operations extremely faster with SIMD.
C#
775
star
12

csbindgen

Generate C# FFI from Rust for automatically brings native code and C native library to .NET and Unity.
Rust
688
star
13

ObservableCollections

High performance observable collections and synchronized views, for WPF, Blazor, Unity.
C#
559
star
14

ProcessX

Simplify call an external process with the async streams in C# 8.0.
C#
453
star
15

YetAnotherHttpHandler

YetAnotherHttpHandler brings the power of HTTP/2 (and gRPC) to Unity and .NET Standard.
C#
354
star
16

UnitGenerator

C# Source Generator to create value-object, inspired by units of measure.
C#
330
star
17

RuntimeUnitTestToolkit

CLI/GUI Frontend of Unity Test Runner to test on any platform.
C#
300
star
18

AlterNats

An alternative high performance NATS client for .NET.
C#
284
star
19

NativeMemoryArray

Utilized native-memory backed array for .NET and Unity - over the 2GB limitation and support the modern API(IBufferWriter, ReadOnlySequence, scatter/gather I/O, etc...).
C#
276
star
20

StructureOfArraysGenerator

Structure of arrays source generator to make CPU Cache and SIMD friendly data structure for high-performance code in .NET and Unity.
C#
262
star
21

MagicPhysX

.NET PhysX 5 binding to all platforms(win, osx, linux) for 3D engine, deep learning, dedicated server of gaming.
Rust
258
star
22

KcpTransport

KcpTransport is a Pure C# implementation of RUDP for high-performance real-time network communication
C#
237
star
23

LogicLooper

A library for building server application using loop-action programming model on .NET.
C#
237
star
24

DFrame

Distributed load testing framework for .NET and Unity.
C#
223
star
25

Utf8StreamReader

Utf8 based StreamReader for high performance text processing.
C#
208
star
26

LitJWT

Lightweight, Fast JWT(JSON Web Token) implementation for .NET.
C#
199
star
27

Claudia

Unofficial Anthropic Claude API client for .NET.
C#
162
star
28

CsprojModifier

CsprojModifier performs additional processing when Unity Editor generates the .csproj.
C#
154
star
29

Utf8StringInterpolation

Successor of ZString; UTF8 based zero allocation high-peformance String Interpolation and StringBuilder.
C#
153
star
30

ValueTaskSupplement

Append supplemental methods(WhenAny, WhenAll, Lazy) to ValueTask.
C#
135
star
31

Kokuban

Simplifies styling strings in the terminal for .NET application.
C#
123
star
32

SlnMerge

SlnMerge merges the solution files when generating solution file by Unity Editor.
C#
114
star
33

GrpcWebSocketBridge

Yet Another gRPC over HTTP/1 using WebSocket implementation, primarily targets .NET platform.
C#
76
star
34

WebSerializer

Convert Object into QueryString/FormUrlEncodedContent for C# HttpClient REST Request.
C#
65
star
35

RandomFixtureKit

Fill random/edge-case value to target type for unit testing, supports both .NET Standard and Unity.
C#
46
star
36

Actions

41
star
37

DocfxTemplate

Patchworked DocFX v2 template for Cysharp
JavaScript
7
star
38

Multicaster

A framework for transparently invoking multiple instances or clients.
C#
5
star
39

com.unity.ide.visualstudio-backport

Backport of com.unity.ide.visualstudio to before Unity 2019.4.21
C#
1
star