Note that there are some explanatory texts on larger screens.

plurals
  1. POCan I create a generic method that takes a value type or a reference type but always returns a nullable type
    text
    copied!<p>This is my method. Note that I am returning the equivalent nullable type for the generic parameter <code>R</code>:</p> <pre><code> public static Nullable&lt;R&gt; GetValue&lt;T, R&gt;(this T a, Expression&lt;Func&lt;T, R&gt;&gt; expression) where T : Attribute where R : struct { if (a == null) return null; PropertyInfo p = GetProperty(expression); if (p == null) return null; return (R)p.GetValue(a, null); } </code></pre> <p>I can use it in a call to get the value of an attribute like this:</p> <pre><code>//I don't throw exceptions for invalid or missing calls //because I want to chain the calls together: int maximumLength4 = instance.GetProperty(x =&gt; x.ToString()) .GetAttribute&lt;StringLengthAttribute&gt;() .GetValue(x =&gt; x.MaximumLength) .GetValueOrDefault(50); </code></pre> <p>I'd like to use the same generic method with strings:</p> <pre><code>//I'd like to use the GetValue generic method with strings as well as integers string erroMessage = instance.GetProperty(x =&gt; x.ToString()) .GetAttribute&lt;StringLengthAttribute&gt;() .GetValue(x =&gt; x.ErrorMessage); </code></pre> <p>but it won't compile:</p> <blockquote> <p>The type 'R' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable'</p> <p>Cannot implicitly convert type 'string?' to 'string'</p> </blockquote> <p>Is there any trick I can use to get the same method signature here and yet get generics to infer the return type as one that can be null?</p> <p>This is some test code to show that it works for integer values:</p> <pre><code>//[StringLength(256)] //public string Name { get; set; } PropertyInfo info = ReflectionAPI.GetProperty&lt;Organisation, String&gt;(x =&gt; x.Name);//not null StringLengthAttribute attr = info.GetAttribute&lt;StringLengthAttribute&gt;();//not null int? maximumLength = attr.GetValue(x =&gt; x.MaximumLength);//256 int? minimumLength = attr.GetValue(x =&gt; x.MinimumLength);//0 PropertyInfo info2 = ReflectionAPI.GetProperty&lt;Organisation, int&gt;(x =&gt; x.ID);//not null StringLengthAttribute attr2 = info2.GetAttribute&lt;StringLengthAttribute&gt;();//null because ID doesn't have the attribute int? maximumLength2 = attr2.GetValue(x =&gt; x.MaximumLength);//null int? minimumLength2 = attr2.GetValue(x =&gt; x.MinimumLength);//null //I can use the GetProperty extension method on an instance Organisation instance = (Organisation)null; PropertyInfo info3 = instance.GetProperty(x =&gt; x.ToString());//null because its a method call not a property StringLengthAttribute attr3 = info3.GetAttribute&lt;StringLengthAttribute&gt;();//null int? maximumLength3 = attr3.GetValue(x =&gt; x.MaximumLength);//null int? minimumLength3 = attr3.GetValue(x =&gt; x.MinimumLength);//null </code></pre> <p>And this is the rest of my <code>ReflectionAPI</code>:</p> <pre><code>public static class ReflectionAPI { public static Nullable&lt;R&gt; GetValue&lt;T, R&gt;(this T a, Expression&lt;Func&lt;T, R&gt;&gt; expression) where T : Attribute { if (a == null) return null; PropertyInfo p = GetProperty(expression); if (p == null) return null; return (R)p.GetValue(a, null); } public static T GetAttribute&lt;T&gt;(this PropertyInfo p) where T : Attribute { if (p == null) return null; return p.GetCustomAttributes(false).OfType&lt;T&gt;().LastOrDefault(); } public static PropertyInfo GetProperty&lt;T, R&gt;(Expression&lt;Func&lt;T, R&gt;&gt; expression) { if (expression == null) return null; MemberExpression memberExpression = expression.Body as MemberExpression; if (memberExpression == null) return null; return memberExpression.Member as PropertyInfo; } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload