@@ -14,16 +14,29 @@ public static class OperatorExtensionsPolyfill
1414 private const string ExplicitOperatorName = "op_Explicit" ;
1515
1616 /// <summary>
17- /// Gets the <paramref name="type" />'s implicit and explicit operators.
17+ /// Gets the <paramref name="type" />'s implicit and explicit operators, optionally of the type
18+ /// specified by the given <paramref name="matcher"/>.
1819 /// </summary>
1920 /// <param name="type">The type from which to retrieve the operators.</param>
21+ /// <param name="matcher">An action specifying the type of implicit operator to retrieve.</param>
2022 /// <returns>The <paramref name="type" />'s implicit and explicit operators.</returns>
21- public static IEnumerable < MethodInfo > GetOperators ( this Type type )
23+ public static IEnumerable < MethodInfo > GetOperators ( this Type type , Action < OperatorSelector > matcher = null )
2224 {
23- return type
25+ var operators = type
2426 . GetPublicStaticMembers ( )
2527 . Where ( m => ( m . Name == ImplicitOperatorName ) || ( m . Name == ExplicitOperatorName ) )
2628 . OfType < MethodInfo > ( ) ;
29+
30+ if ( matcher == null )
31+ {
32+ return operators ;
33+ }
34+
35+ var selector = new OperatorSelector ( ) ;
36+
37+ matcher . Invoke ( selector ) ;
38+
39+ return operators . Where ( selector . Matches ) ;
2740 }
2841
2942 /// <summary>
@@ -39,19 +52,22 @@ public static IEnumerable<MethodInfo> GetImplicitOperators(this Type type)
3952 }
4053
4154 /// <summary>
42- /// Gets the <paramref name="type" />'s implicit operator with the given
43- /// <typeparamref name="TReturn">return type</typeparamref >.
55+ /// Gets the <paramref name="type" />'s implicit operator of the type specified by the given
56+ /// <paramref name="matcher"/ >.
4457 /// </summary>
45- /// <typeparam name="TReturn">The return type of the implicit operator to retrieve.</typeparam>
4658 /// <param name="type">The type from which to retrieve the operator.</param>
59+ /// <param name="matcher">An action specifying the type of implicit operator to retrieve.</param>
4760 /// <returns>
48- /// The <paramref name="type" />'s implicit operator with the given
49- /// <typeparamref name="TReturn">return type</typeparamref >, or null if none exists.
61+ /// The <paramref name="type" />'s implicit operator of the type specified by the given
62+ /// <paramref name="matcher"/ >, or null if none exists.
5063 /// </returns>
51- public static MethodInfo GetImplicitOperator < TReturn > ( this Type type )
64+ public static MethodInfo GetImplicitOperator ( this Type type , Action < OperatorSelector > matcher )
5265 {
53- return type . GetImplicitOperators ( )
54- . FirstOrDefault ( o => o . ReturnType == typeof ( TReturn ) ) ;
66+ var selector = new OperatorSelector ( ) ;
67+
68+ matcher ? . Invoke ( selector ) ;
69+
70+ return type . GetImplicitOperators ( ) . FirstOrDefault ( selector . Matches ) ;
5571 }
5672
5773 /// <summary>
@@ -67,19 +83,68 @@ public static IEnumerable<MethodInfo> GetExplicitOperators(this Type type)
6783 }
6884
6985 /// <summary>
70- /// Gets the <paramref name="type" />'s explicit operator with the given
71- /// <typeparamref name="TReturn">return type</typeparamref >.
86+ /// Gets the <paramref name="type" />'s explicit operator of the type specified by the given
87+ /// <paramref name="matcher"/ >.
7288 /// </summary>
73- /// <typeparam name="TReturn">The return type of the explicit operator to retrieve.</typeparam>
7489 /// <param name="type">The type from which to retrieve the operator.</param>
90+ /// <param name="matcher">An action specifying the type of explicit operator to retrieve.</param>
7591 /// <returns>
76- /// The <paramref name="type" />'s explicit operator with the given
77- /// <typeparamref name="TReturn">return type</typeparamref >, or null if none exists.
92+ /// The <paramref name="type" />'s explicit operator of the type specified by the given
93+ /// <paramref name="matcher"/ >, or null if none exists.
7894 /// </returns>
79- public static MethodInfo GetExplicitOperator < TReturn > ( this Type type )
95+ public static MethodInfo GetExplicitOperator ( this Type type , Action < OperatorSelector > matcher )
96+ {
97+ var selector = new OperatorSelector ( ) ;
98+
99+ matcher ? . Invoke ( selector ) ;
100+
101+ return type . GetExplicitOperators ( ) . FirstOrDefault ( selector . Matches ) ;
102+ }
103+
104+ #region Helper Class
105+
106+ /// <summary>
107+ /// Provides options for selecting a particular operator.
108+ /// </summary>
109+ public class OperatorSelector
80110 {
81- return type . GetExplicitOperators ( )
82- . FirstOrDefault ( o => o . ReturnType == typeof ( TReturn ) ) ;
111+ private Type _fromType ;
112+ private Type _toType ;
113+
114+ internal OperatorSelector ( )
115+ {
116+ }
117+
118+ /// <summary>
119+ /// Select the operator which converts the given <typeparamref name="TInput">type</typeparamref>
120+ /// to the type in question.
121+ /// </summary>
122+ /// <typeparam name="TInput">The input type of the operator to select.</typeparam>
123+ public void From < TInput > ( ) => _fromType = typeof ( TInput ) ;
124+
125+ /// <summary>
126+ /// Select the operator which converts the type in question to the given
127+ /// <typeparamref name="TReturn">return type</typeparamref>.
128+ /// </summary>
129+ /// <typeparam name="TReturn">The output type of the operator to select.</typeparam>
130+ public void To < TReturn > ( ) => _toType = typeof ( TReturn ) ;
131+
132+ internal bool Matches ( MethodInfo @operator )
133+ {
134+ if ( _toType != null )
135+ {
136+ return @operator . ReturnType == _toType ;
137+ }
138+
139+ if ( _fromType != null )
140+ {
141+ return @operator . GetParameters ( ) [ 0 ] . ParameterType == _fromType ;
142+ }
143+
144+ throw new InvalidOperationException ( "No operator From or To type specified." ) ;
145+ }
83146 }
147+
148+ #endregion
84149 }
85150}
0 commit comments