重要
現在の Roslyn/Source Generator には、参照プロジェクトのプライベート メンバーへのアクセスに制限があります。さらに、プライベート メンバーにアクセスすると、IDE では正常に動作しても、ビルド プロセス中に失敗するという状況が発生する可能性があります。詳細については、Roslyn の問題「MetadataImportOptions.All がソース ジェネレーターで機能しない?」を参照してください。混乱を避けるため、ソース ジェネレーターと非公開メンバーとの関係が改善されるまで、これをアーカイブしておきます。
単体テストとランタイム用のソース ジェネレーターと .NET 8 UnsafeAccessor ベースの高性能で厳密に型指定されたプライベート アクセサー。
[GeneratePrivateProxy(typeof(TargetType))]
アクセサー プロキシを生成します。
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 ;
生成されたコードは完全に型指定されており、IntelliSense 経由でプライベート フィールドにアクセスでき、プライベート フィールドが変更された場合はコンパイラ エラーを確認できます。
ref
、 out
、 in
、およびref readonly
メソッド パラメータをサポートreadonly
フィールドとプロパティをサポートref
リターンをサポートたとえば、これは可変構造体と静的、参照戻り、およびコンストラクターのサンプルです。
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 ) ;
このライブラリは NuGet 経由で配布されます。最小要件は .NET 8 および C# 12 です。
PM> インストールパッケージ PrivateProxy
パッケージはアナライザーのみを提供し、生成されたコードは他のライブラリに依存しません。
GeneratePrivateProxy
ターゲットのタイプとメンバー
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 ) { }
}
プロキシ タイプは、 class
=> class
または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 には 2 つのコンストラクターがあり、 PrivateProxyGenerateKinds
パラメーターを使用すると、生成メンバーの種類を構成できます。
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 ,
}
現在、次の機能はサポートされていません
String
)このライブラリは、MIT ライセンスに基づいてライセンスされています。