@@ -23,6 +23,8 @@ public void AssertIs(AssertNode node) {
2323
2424 _logger ? . Write ( $ "{ node . MemberName } : { node . TargetType ? . GetFriendlyName ( ) ?? "(null)" } = ") ;
2525 try {
26+ if ( TryPredicateAssertIs ( targetType , actual , expected , node ) ) { return ; }
27+
2628 // null 比較
2729 if ( targetType is null ) {
2830 if ( ! ( actual is null ) ) { throw new PrimitiveAssertFailedException ( node , "ターゲット型は null ですが、actual は非 null です。" , _message ) ; }
@@ -79,6 +81,30 @@ private void WriteLog(AssertNode node, string additionalMessage) {
7981 _logger . WriteLine ( ) ;
8082 }
8183
84+ private bool TryPredicateAssertIs ( Type ? targetType , object ? actual , object ? expected , AssertNode node ) {
85+ if ( expected is null ) { return false ; }
86+
87+ if ( expected is AssertPredicate predicate ) {
88+ if ( ! predicate ( actual ) ) { throw new PrimitiveAssertFailedException ( node , "actual はカスタム条件に一致しませんでした。" , _message ) ; }
89+
90+ WriteLog ( node , "actual はカスタム条件に一致しました。" ) ;
91+ return true ;
92+ }
93+
94+ Type expectedType = expected . GetType ( ) ;
95+ if ( expectedType . IsGenericType && expectedType . GetGenericTypeDefinition ( ) == typeof ( AssertPredicate < > ) ) {
96+ Type genericType = expectedType . GetGenericArguments ( ) [ 0 ] ;
97+
98+ if ( ! genericType . IsAssignableFrom ( actual ? . GetType ( ) ) ) { throw new PrimitiveAssertFailedException ( node , "actual はカスタム条件の型引数にキャストできませんでした。" , _message ) ; }
99+ if ( ! ( bool ) expectedType . GetMethod ( "Invoke" ) . Invoke ( expected , new [ ] { actual } ) ) { throw new PrimitiveAssertFailedException ( node , "actual はカスタム条件に一致しませんでした。" , _message ) ; }
100+
101+ WriteLog ( node , "actual はカスタム条件に一致しました。" ) ;
102+ return true ;
103+ }
104+
105+ return false ;
106+ }
107+
82108 private bool TryNumericAssertIs ( Type targetType , object actual , object expected , AssertNode node ) {
83109 if ( ! Numeric . IsNumeric ( targetType ) ) { return false ; }
84110
0 commit comments