Skip to content

Commit

Permalink
Merge pull request #668 from stakx/enhancement/nullable-reference-typ…
Browse files Browse the repository at this point in the history
…e-annotations

Add nullable reference type annotations to DynamicProxy's public API
  • Loading branch information
stakx authored Aug 30, 2024
2 parents 3374796 + 7122b6c commit 00642c9
Show file tree
Hide file tree
Showing 32 changed files with 824 additions and 720 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Enhancements:
- Two new generic method overloads `proxyGenerator.CreateClassProxy<TClass>([options], constructorArguments, interceptors)` (@backstromjoel, #636)
- Allow specifying which attributes should always be copied to proxy class by adding attribute type to `AttributesToAlwaysReplicate`. Previously only non-inherited, with `Inherited=false`, attributes were copied. (@shoaibshakeel381, #633)
- Support for C# 8+ [default interface methods](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods) in interface and class proxies without target (@stakx, #661)
- DynamicProxy's public API has been augmented with nullable reference type annotations (@stakx, #668)

Bugfixes:
- `ArgumentException`: "Could not find method overriding method" with overridden class method having generic by-ref parameter (@stakx, #657)
Expand Down
257 changes: 129 additions & 128 deletions ref/Castle.Core-net462.cs

Large diffs are not rendered by default.

248 changes: 125 additions & 123 deletions ref/Castle.Core-net6.0.cs

Large diffs are not rendered by default.

247 changes: 124 additions & 123 deletions ref/Castle.Core-netstandard2.0.cs

Large diffs are not rendered by default.

247 changes: 124 additions & 123 deletions ref/Castle.Core-netstandard2.1.cs

Large diffs are not rendered by default.

51 changes: 51 additions & 0 deletions src/Castle.Core/Compatibility/NullStateStaticAnalysisAttributes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2004-2023 Castle Project - http://www.castleproject.org/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace System.Diagnostics.CodeAnalysis
{
using System;

#if !NETSTANDARD2_1_OR_GREATER && !NETCOREAPP3_0_OR_GREATER
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
internal sealed class DoesNotReturnAttribute : Attribute
{
}
#endif

#if !NET5_0_OR_GREATER
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
internal sealed class MemberNotNullAttribute : Attribute
{
public MemberNotNullAttribute(string member)
{
Members = new[] { member };
}

public string[] Members { get; }
}
#endif

#if !NETSTANDARD2_1_OR_GREATER && !NETCOREAPP3_0_OR_GREATER
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class NotNullWhenAttribute : Attribute
{
public NotNullWhenAttribute(bool returnValue)
{
ReturnValue = returnValue;
}

public bool ReturnValue { get; }
}
#endif
}
31 changes: 17 additions & 14 deletions src/Castle.Core/DynamicProxy/AbstractInvocation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,30 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#nullable enable

namespace Castle.DynamicProxy
{
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;

public abstract class AbstractInvocation : IInvocation
{
private readonly IInterceptor[] interceptors;
private readonly object[] arguments;
private readonly object?[] arguments;
private int currentInterceptorIndex = -1;
private Type[] genericMethodArguments;
private Type[]? genericMethodArguments;
private readonly MethodInfo proxiedMethod;
protected readonly object proxyObject;

protected AbstractInvocation(
object proxy,
IInterceptor[] interceptors,
MethodInfo proxiedMethod,
object[] arguments)
object?[] arguments)
{
Debug.Assert(proxiedMethod != null);
proxyObject = proxy;
this.interceptors = interceptors;
this.proxiedMethod = proxiedMethod;
Expand All @@ -45,13 +47,13 @@ public void SetGenericMethodArguments(Type[] arguments)
genericMethodArguments = arguments;
}

public abstract object InvocationTarget { get; }
public abstract object? InvocationTarget { get; }

public abstract Type TargetType { get; }
public abstract Type? TargetType { get; }

public abstract MethodInfo MethodInvocationTarget { get; }
public abstract MethodInfo? MethodInvocationTarget { get; }

public Type[] GenericArguments
public Type[]? GenericArguments
{
get { return genericMethodArguments; }
}
Expand All @@ -71,7 +73,7 @@ public MethodInfo GetConcreteMethod()
return EnsureClosedMethod(Method);
}

public MethodInfo GetConcreteMethodInvocationTarget()
public MethodInfo? GetConcreteMethodInvocationTarget()
{
// it is ensured by the InvocationHelper that method will be closed
var method = MethodInvocationTarget;
Expand All @@ -80,19 +82,19 @@ public MethodInfo GetConcreteMethodInvocationTarget()
return method;
}

public object ReturnValue { get; set; }
public object? ReturnValue { get; set; }

public object[] Arguments
public object?[] Arguments
{
get { return arguments; }
}

public void SetArgumentValue(int index, object value)
public void SetArgumentValue(int index, object? value)
{
arguments[index] = value;
}

public object GetArgumentValue(int index)
public object? GetArgumentValue(int index)
{
return arguments[index];
}
Expand Down Expand Up @@ -137,6 +139,7 @@ public IInvocationProceedInfo CaptureProceedInfo()

protected abstract void InvokeMethodOnTarget();

[DoesNotReturn]
protected void ThrowOnNoTarget()
{
// let's try to build as friendly message as we can
Expand All @@ -152,7 +155,7 @@ protected void ThrowOnNoTarget()

string methodKindIs;
string methodKindDescription;
if (Method.DeclaringType.IsClass && Method.IsAbstract)
if (Method.DeclaringType!.IsClass && Method.IsAbstract)
{
methodKindIs = "is abstract";
methodKindDescription = "an abstract method";
Expand Down
6 changes: 4 additions & 2 deletions src/Castle.Core/DynamicProxy/AllMethodsHook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#nullable enable

namespace Castle.DynamicProxy
{
using System;
Expand All @@ -32,7 +34,7 @@ public class AllMethodsHook : IProxyGenerationHook

public virtual bool ShouldInterceptMethod(Type type, MethodInfo methodInfo)
{
return SkippedTypes.Contains(methodInfo.DeclaringType) == false;
return SkippedTypes.Contains(methodInfo.DeclaringType!) == false;
}

public virtual void NonProxyableMemberNotification(Type type, MemberInfo memberInfo)
Expand All @@ -43,7 +45,7 @@ public virtual void MethodsInspected()
{
}

public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj != null && obj.GetType() == GetType();
}
Expand Down
Loading

0 comments on commit 00642c9

Please sign in to comment.