/
Delegate.cs
122 lines (94 loc) · 4.95 KB
/
Delegate.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
namespace System
{
public abstract partial class Delegate : ICloneable, ISerializable
{
public virtual object Clone() => MemberwiseClone();
[return: NotNullIfNotNull(nameof(a))]
[return: NotNullIfNotNull(nameof(b))]
public static Delegate? Combine(Delegate? a, Delegate? b)
{
if (a is null)
return b;
return a.CombineImpl(b);
}
public static Delegate? Combine(params Delegate?[]? delegates)
{
if (delegates == null || delegates.Length == 0)
return null;
Delegate? d = delegates[0];
for (int i = 1; i < delegates.Length; i++)
d = Combine(d, delegates[i]);
return d;
}
// V2 api: Creates open or closed delegates to static or instance methods - relaxed signature checking allowed.
public static Delegate CreateDelegate(Type type, object? firstArgument, MethodInfo method) => CreateDelegate(type, firstArgument, method, throwOnBindFailure: true)!;
// V1 api: Creates open delegates to static or instance methods - relaxed signature checking allowed.
public static Delegate CreateDelegate(Type type, MethodInfo method) => CreateDelegate(type, method, throwOnBindFailure: true)!;
// V1 api: Creates closed delegates to instance methods only, relaxed signature checking disallowed.
[RequiresUnreferencedCode("The target method might be removed")]
public static Delegate CreateDelegate(Type type, object target, string method) => CreateDelegate(type, target, method, ignoreCase: false, throwOnBindFailure: true)!;
[RequiresUnreferencedCode("The target method might be removed")]
public static Delegate CreateDelegate(Type type, object target, string method, bool ignoreCase) => CreateDelegate(type, target, method, ignoreCase, throwOnBindFailure: true)!;
// V1 api: Creates open delegates to static methods only, relaxed signature checking disallowed.
public static Delegate CreateDelegate(Type type, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type target, string method) => CreateDelegate(type, target, method, ignoreCase: false, throwOnBindFailure: true)!;
public static Delegate CreateDelegate(Type type, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type target, string method, bool ignoreCase) => CreateDelegate(type, target, method, ignoreCase, throwOnBindFailure: true)!;
protected virtual Delegate CombineImpl(Delegate? d) => throw new MulticastNotSupportedException(SR.Multicast_Combine);
protected virtual Delegate? RemoveImpl(Delegate d) => d.Equals(this) ? null : this;
public virtual Delegate[] GetInvocationList() => new Delegate[] { this };
public object? DynamicInvoke(params object?[]? args)
{
return DynamicInvokeImpl(args);
}
public virtual void GetObjectData(SerializationInfo info, StreamingContext context) => throw new PlatformNotSupportedException();
public MethodInfo Method => GetMethodImpl();
public static Delegate? Remove(Delegate? source, Delegate? value)
{
if (source == null)
return null;
if (value == null)
return source;
if (!InternalEqualTypes(source, value))
throw new ArgumentException(SR.Arg_DlgtTypeMis);
return source.RemoveImpl(value);
}
public static Delegate? RemoveAll(Delegate? source, Delegate? value)
{
Delegate? newDelegate;
do
{
newDelegate = source;
source = Remove(source, value);
}
while (newDelegate != source);
return newDelegate;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Delegate? d1, Delegate? d2)
{
// Test d2 first to allow branch elimination when inlined for null checks (== null)
// so it can become a simple test
if (d2 is null)
{
return d1 is null;
}
return ReferenceEquals(d2, d1) ? true : d2.Equals((object?)d1);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Delegate? d1, Delegate? d2)
{
// Test d2 first to allow branch elimination when inlined for not null checks (!= null)
// so it can become a simple test
if (d2 is null)
{
return d1 is not null;
}
return ReferenceEquals(d2, d1) ? false : !d2.Equals(d1);
}
}
}