GregC
GregC

Reputation: 7997

Accessing constants with a dynamic keyword

This is a follow-up to How to invoke static method in C#4.0 with dynamic type?

Is there a way to remove duplication when working with double.MaxValue, int.MaxValue, etc. by using dynamic keyword and/or generics?

Contrived example:

  T? Transform<T>(Func<T?> continuation)
     where T : struct
  {
     return typeof(T).StaticMembers().MaxValue;
  }

Upvotes: 0

Views: 398

Answers (2)

GregC
GregC

Reputation: 7997

With a little style and flair, same code:

  public override bool TryGetMember(GetMemberBinder binder, out object result)
  {
     PropertyInfo prop = _type.GetProperty(binder.Name,
        BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public);

     if (prop != null)
     {
        result = prop.GetValue(null, null);
        return true;
     }

     FieldInfo field = _type.GetField(binder.Name,
        BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public);

     if (field != null)
     {
        result = field.GetValue(null);
        return true;
     }

     result = null;
     return false;
  }

And a cache class, to avoid creating unneeded objects:

public static class StaticMembersDynamicWrapperExtensions
{
   static Dictionary<Type, DynamicObject> cache = 
      new Dictionary<Type, DynamicObject>
      {
         {typeof(double), new StaticMembersDynamicWrapper(typeof(double))},
         {typeof(float), new StaticMembersDynamicWrapper(typeof(float))},
         {typeof(uint), new StaticMembersDynamicWrapper(typeof(uint))},
         {typeof(int), new StaticMembersDynamicWrapper(typeof(int))},
         {typeof(sbyte), new StaticMembersDynamicWrapper(typeof(sbyte))}
      };

   /// <summary>
   /// Allows access to static fields, properties, and methods, resolved at run-time.
   /// </summary>
   public static dynamic StaticMembers(this Type type)
   {
      DynamicObject retVal;
      if (!cache.TryGetValue(type, out retVal))
         return new StaticMembersDynamicWrapper(type);

      return retVal;
   }
}

Upvotes: 0

Andrey
Andrey

Reputation: 60065

Modify class StaticMembersDynamicWrapper in this way:

  public override bool TryGetMember(GetMemberBinder binder, out object result) { 
    PropertyInfo prop = _type.GetProperty(binder.Name, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public); 
    if (prop == null) { 
        FieldInfo field = _type.GetField(binder.Name, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public); 
        if (field == null)
        {
            result = null;
            return false; 
        }
        else
        {
            result = field.GetValue(null, null);
            return true; 
        }
    } 

    result = prop.GetValue(null, null); 
    return true; 
}

Problem of your code is that it only retrieves properties, but constants are actually fields.

Upvotes: 1

Related Questions