Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add nullable reference type annotations to DynamicProxy's public API #668

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading