-1

How can I convert my object to its type by typecasting with Reflection? I've searched this issue on the internet, I found some ways but they didn't suitable for my problem. This is my code and I need to cast fields in my class that is the type of some another class dynamical.

If you see the following code, you'll find out I added four if for each field casting. I am looking for a way to refactor this bunch of code fewer lines.

    public void CheckObjectFormatValues(object o)
    {
        FieldInfo[] fields = o.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
        foreach (System.Reflection.FieldInfo prp in fields)
        {

            if (prp.FieldType.BaseType != typeof(ValueType))
            {
                if (prp.FieldType.FullName == "IServiceProvider.Datacontracts.ArrivalType")
                    CheckObjectFormatValues((ArrivalType)prp.GetValue(o));

                if (prp.FieldType.FullName == "IServiceProvider.Datacontracts.Cell")
                    CheckObjectFormatValues((Cell)prp.GetValue(o));

                if (prp.FieldType.FullName == "IServiceProvider.Datacontracts.ObjectType")
                    CheckObjectFormatValues((ObjectType)prp.GetValue(o));

                if (prp.FieldType.FullName == "IServiceProvider.Datacontracts.ObjAction")
                    CheckObjectFormatValues((ObjAction)prp.GetValue(o));
            }
            else
            {
                var value = prp.GetValue(o).ToString();
                if (value == "-1")
                    throw new Exception("Error");
            }
        }
    }

Is there any way to refactor my If block with recursive function and cast dynamically?

Sasan
  • 644
  • 9
  • 29
  • `if (prp.FieldType == typeof(IServiceProvider.Datacontracts.ArrivalType))`? Of course this assumes you have access to that type. – MakePeaceGreatAgain Sep 16 '19 at 09:14
  • What is the point of casting value(prp.GetValue(o)) to concrete type and then call CheckObject... which accepts object type again? – Viktor Arsanov Sep 16 '19 at 09:15
  • DO all the objects you want to call recursively share an interface and/or base class? If not, how do you distinguish the ones you want to call recursively? – Jamiec Sep 16 '19 at 09:16
  • @ HimBromBeere - Here I manually check that where this FieldType== ArrivalType or not. If so, cast it and sent to the function for reflection. But I want to change it to automatic casting, not to say specifically type of field. – Sasan Sep 16 '19 at 09:24
  • @ Viktor Arsanov - I cast to the class that this field is, and send to the function to access its fields and check their values. – Sasan Sep 16 '19 at 09:27
  • @Jamiec - No some objects(fields) are different class. – Sasan Sep 16 '19 at 09:28
  • Yes, but there is the only method CheckObjectFormatValues(object ...) or you have other overloads of the method? – Viktor Arsanov Sep 16 '19 at 09:31
  • With the current code I don't see what's gonna change if you remove those type casts. – Viktor Arsanov Sep 16 '19 at 09:32

1 Answers1

1

There is no need to cast at all, your method takes object as its parameter

public void CheckObjectFormatValues(object o)
{
    FieldInfo[] fields = o.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
    foreach (System.Reflection.FieldInfo prp in fields)
    {

        if (prp.FieldType.BaseType != typeof(ValueType))
        {
            if(ShouldRecurse(prp.FieldType))
                 CheckObjectFormatValues(prp.GetValue(o));               
        }
        else
        {
            var value = prp.GetValue(o).ToString();
            if (value == "-1")
                throw new Exception("Error");
        }
    }
}

private bool ShouldRecurse(Type fieldType)
{
    // TODO
}

As you can see, all you need is some logic to determine if, given a Type (The FieldType) the method should recall itself. You could do this using an attribute on the class, or a shared interface, or any number of other ways.

Personally, I'd go with an attribute:

public class RequiresCheckObjectFormatValuesAttribute: Attribute 
{}

[RequiresCheckObjectFormatValues]
public class ArrivalType{ ... }

[RequiresCheckObjectFormatValues]
public class Cell{ ... }

And then your ShouldRecurse method is simply:

public bool ShouldRecurse(Type fieldType)
{
    return fieldType.GetCustomAttributes<RequiresCheckObjectFormatValuesAttribute>().Length>0;
}
Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • Why you define another function(ShouldRecurse)? I want to call 'CheckObjectFormatValues' recursively – Sasan Sep 16 '19 at 10:25
  • @SasanK just to demonstrate that the decision whether to recurse or not is easy to abstract. There is no *need* to have a separate function, it was just helpful for demonstration. You could put the logic for that (it is only 1 line, in my example) right into the recursive function itself. – Jamiec Sep 16 '19 at 10:29
  • @ Jamiec - In brief, I need to cast (ArrivalType)prp.GetValue(o)) dynamically and extract these four castings in one line. Not for each type, I add another casting. – Sasan Sep 16 '19 at 10:39
  • @SasanK I'm sorry, but I do not understand. What does "extract these four castings in one line" actually mean? What are you *really* trying to do? – Jamiec Sep 16 '19 at 10:41
  • @ Jamiec - I want to the part of the casting would be dynamical. For example something like this: CheckObjectFormatValues((prp.GetType(o))prp.GetValue(o)); – Sasan Sep 16 '19 at 10:49
  • 1
    @SasanK But as ive pointed out above - there is absolutely no need to cast *anything* Your method takes `object` and `GetValue` returns `object`. You have an [XY Problem](http://xyproblem.info). You think you need something to solve the problem, but youre solving it the wrong way to start with. – Jamiec Sep 16 '19 at 10:51
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/199508/discussion-between-jamiec-and-sasan-k). – Jamiec Sep 16 '19 at 10:58