Getting operators using Reflection

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Plater
    Recognized Expert Expert
    • Apr 2007
    • 7872

    Getting operators using Reflection

    I am having some trouble finding a way to retreive the operators from a custom class.

    In a simplified example I have the following:
    [code=c#]
    public class Namespace1.Addr ess
    {
    public string City;
    public string State;

    public static implicit operator Address(Namespa ce2.Address value)
    { /* Logic to transform */ }
    }

    public class Namespace2.Addr ess
    {
    public string City;
    public string State;

    public static implicit operator Address(Namespa ce1.Address value)
    { /* Logic to transform */ }
    }
    [/code]

    Now I want to use reflection to get the custom operators that exist there (Actually what I want is a bit different, but I *think* this will lead me to THAT goal), and then invoke them?
    [code#]
    Type myT=Namespace1. Address.GetType ();
    MemberInfo[] mis=myT.GetMemb ers(BindingFlag s.Public|Bindin gFlags.Static);
    [/code]
    Now after starting this question I figured out that using the Static bindingflag gave me the op_implicit that I had defined.
    I think I'm just not thinking this through well enough.

    I have a number of classes just like that Address class, and I want to write a conversion function that checks for the existance of an operator (implicit or explicit) between two classes, and then invokes it.
    A universal converter if you will.

    I have a reflection-based function that uses getFields() that works on the Address classes without the operators being needed. But chokes on classes such as this:

    [code=c#]
    public class Namespace1.Loca tion
    {
    public string Name;
    public Address Place;
    }

    public class Namespace2.Loca tion
    {
    public string Name;
    public Address Place;
    }
    [/code]
    (Since the two address classes are not the same, using invokeMember fails).


    I'm not sure my question is clear, but if anyone has ideas I can attempt to make it more clear.
  • Plater
    Recognized Expert Expert
    • Apr 2007
    • 7872

    #2
    I think I may have found what I am looking for:

    [code=c#]
    //EndType is the type I want to PRODUCE
    //StartType is the type I am pulling data FROM
    MethodInfo mi = EndType.GetMeth od(
    "op_Implici t",
    (BindingFlags.P ublic | BindingFlags.St atic),
    null,
    new Type[] { StartType },
    new ParameterModifi er[0]
    );
    //Now if mi is NOT null, it means there is an operator that allows for converting StartType to EndType, if it is null, there isn't one
    [/code]

    Comment

    • Plater
      Recognized Expert Expert
      • Apr 2007
      • 7872

      #3
      So I think I have what I wanted, it's been working well.
      [code=c#]
      public static class ShippingConvers ion
      {
      private static BindingFlags basePropertyFla gs = BindingFlags.In stance | BindingFlags.No nPublic | BindingFlags.Pu blic;
      public static object ConvertOP(objec t StartObject, Type EndType)
      {
      object retval = null;
      Type[] SearchTypes = (StartObject != null) ? new Type[] { StartObject.Get Type() } : new Type[0];
      MethodInfo mi = EndType.GetMeth od("op_Explicit ", (BindingFlags.P ublic | BindingFlags.St atic), null, SearchTypes, new ParameterModifi er[0]);
      if (mi == null) mi = EndType.GetMeth od("op_Implicit ", (BindingFlags.P ublic | BindingFlags.St atic), null, SearchTypes, new ParameterModifi er[0]);
      if (mi != null)//there is a conversion operator!
      { retval = EndType.InvokeM ember(mi.Name, BindingFlags.In vokeMethod | (BindingFlags.P ublic | BindingFlags.St atic), null, null, new object[] { StartObject }); }
      return retval;
      }
      public static object Convert(object StartObject, Type EndType)
      {
      object retval = null;

      Type StartType = StartObject.Get Type();
      retval = EndType.InvokeM ember("", BindingFlags.Cr eateInstance, null, null, new object[0]);
      PropertyInfo[] pis = EndType.GetProp erties(baseProp ertyFlags);
      foreach (PropertyInfo oI in pis)//you should probably use getFields, in case there is no setter, but in my case this is -safe-(ish)
      {
      PropertyInfo thisFIs = StartType.GetPr operty(oI.Name, basePropertyFla gs);
      if ((thisFIs != null))
      {
      object cVal = StartType.Invok eMember(thisFIs .Name, basePropertyFla gs | BindingFlags.Ge tProperty, null, StartObject, new object[0]);
      if (thisFIs.Proper tyType == oI.PropertyType )
      { EndType.InvokeM ember(thisFIs.N ame, basePropertyFla gs | BindingFlags.Se tProperty, null, retval, new object[] { cVal }); }
      else
      {//check for operator for it?
      object o = ConvertOP(cVal, oI.PropertyType );
      if (o != null) EndType.InvokeM ember(thisFIs.N ame, basePropertyFla gs | BindingFlags.Se tProperty, null, retval, new object[] { o });
      }
      }
      }

      return retval;
      }
      } //end of class
      [/code]

      Anything that is the -same- type and -same- name gets set. If they are custom classes, the code checks to see if there are implicit/explict operators for it. (Those are used for type-casting)

      I'm pretty pleased that this is working.

      Comment

      • GaryTexmo
        Recognized Expert Top Contributor
        • Jul 2009
        • 1501

        #4
        Nifty... nice job :)

        Comment

        Working...