-2

I have been struggling with a the concept mentioned in the title. I've done a good deal of research and have found some good examples and I have attempted to implement some of them but have reached a road block.

I initially had a class that looked like this:

namespace sysVer
{
    public class testSuite
    {
        /* there is a bunch of test hardware setup
         * and acquisition also that is not shown
         */
        public struct testResultInfo
        {
            public testStatus testStat;
            public bool warning, error;
            public string warnStr, errStr, infoStr, muxDataStr;
            public double measDecVal;
            public Int16 measIntVal;
        };
        
        // NOTE there is no default constructor
        
        public static testResultInfo testCase1()
        {
            
        }
        public static testResultInfo testCase2()
        {
            
        }
        public static testResultInfo testCase3()
        {
            
        }
        // there are about 100 more
    }
}

And using a windows form with 105 of checkboxes and a dictionary to determine which function the user wants to run, I was able to call the functions by a string using Invoke Member as follows:

// first attempt
namespace sysVer
{
    public partial class SysVerForm : Form
    {
        public static Pdgu1553ver.testResultInfo tcResult = new Pdgu1553ver.testResultInfo ( )
        {
            testStat = Pdgu1553ver.testStatus.pass,
            warning = true,
            error = true,
            warnStr = "This is a warning",
            errStr = "This is an error",
            infoStr = "This is info",
            muxDataStr = "Mux data of some sort",
            measDecVal = 69.69,
            measIntVal = 69
        };
        
        // for loop that iterates over checkbox checked items
        foreach ( var checkedItem in checkedItems )
        {
            var funcName = "";
            
            // retrieve function name from dictionary
            tcToFuncDic.TryGetValue ( checkedItem.ToString ( ), out funcName );
            
            tcResult = ( testSuite.testResultInfo ) typeof ( testSuite ).InvokeMember 
                (
                    funcName,
                    BindingFlags.InvokeMethod |
                    BindingFlags.Public |
                    BindingFlags.Static,
                    null,
                    null,
                    null 
                );
        }
    }
}

But I ran into a problem here. When InvokeMember is called the static method is executed and a return type is received but I am not sure if the method is just called or is an actual instance of the class created using the default constructor? I started noticing that private attributes of this class set during one call were not there during another call to a different static function that needed them.

I assumed that I needed an instance of my class so I changed to the following:

namespace sysVer
{
    public class testSuite
    {
        /* there is a bunch of test hardware setup
         * and acquisition also that is not shown
         */
        public struct testResultInfo
        {
            public testStatus testStat;
            public bool warning, error;
            public string warnStr, errStr, infoStr, muxDataStr;
            public double measDecVal;
            public Int16 measIntVal;
        };
        
        // constructor
        public testSuite()
        {
            /* Here I initialize hardware, set variables, and
             * run a few other tasks.  All of which need to be done
             * an exist before this object can be used
             */
        }
        
        public testResultInfo testCase1()
        {
            
        }
        public testResultInfo testCase2()
        {
            
        }
        public testResultInfo testCase3()
        {
            
        }
        //... there are about 100 more
    }
}

Now, I hit another wall. I needed to do something like this:

testSuite myTest = new testSuite();
var blah = myTest.InvokeMember(
                    funcName,
                    BindingFlags.InvokeMethod |
                    BindingFlags.Public |
                    BindingFlags.Static,
                    null,
                    null,
                    null 
                );

But my class does not contain that method. Looking into that I learned that I could change my class to inherit from 'Type' and that I would have to override about 50 or so abstracts from 'Type'. I started down this path but feel that it is likely more work than I need to do here.

I need to have an instance of my class and need to be able to deduce at runtime which non-static method to call. Of the many posts I've read these two: How to invoke a non static method by reflection and invoke non static method in c# seem to be pushing me in the right direction but I'm still missing something somewhere.

I've already put lots of time in overriding all those functions but am stuck there with how to actually implement the overridden InvokeMember function, I'd hate to undo all that work to try to do something else at this point.

As always, any advice is greatly appreciate. Thank you for your time and consideration.

Michael Riley
  • 67
  • 1
  • 10
  • 1
    `Looking into that I learned that I could change my class to inherit from 'Type'` - I do wonder how you could learn that. No, you do not inherit from `Type`. You *get* the type, get the method info from it, and `Invoke` that method info like it is clearly laid out in the [very answer you are linking to](https://stackoverflow.com/a/35036582/11683). – GSerg Jul 09 '21 at 19:03
  • Your question very unclear. You seem to have tried a lot of different things that are probably not anything like what you want. For sure, inheriting `Type` is going to be completely wrong. In practically every case, if you want to call a non-static method, it should be _only_ because you already have a relevant _instance_ of the object with which to call the method, and in that case any of the many "call method by reflection" Q&A we already have here should suffice. Please [edit your question](https://stackoverflow.com/posts/68321572/edit) to improve. Remove all of the non-essential ... – Peter Duniho Jul 09 '21 at 19:05
  • ... information (which appears to be most of what you posted above), while making sure to include a [mcve] that shows the closest to success you've gotten, along with a clear explanation of what that code does, what you want instead, and what _specifically_ you need help with. – Peter Duniho Jul 09 '21 at 19:05
  • @GSerg, This is my first time messing with this stuff, but on the [link](https://learn.microsoft.com/en-us/dotnet/api/system.type?view=net-5.0#notes-to-implementers) Type Class site under the section 'Notes to Implementers' it states 'When you inherit from Type, you must override the following members:', so I figured I needed to inherit from it. Maybe that was a mistake – Michael Riley Jul 09 '21 at 19:07
  • @MichaelRiley Those are notes to implementers. You aren't one. You can find such notes on many classes that you can use without implementing them yourself. – GSerg Jul 09 '21 at 19:11
  • "I started noticing that private attributes of this class set during one call were not there during another call to a different static function that needed them....I assumed that I needed an instance of my class " ??? Why would you assume that??? That doesn't even make sense. I suggest you put a watch on the variables of interest and step through your code to see when they get changed. – John Wu Jul 09 '21 at 19:11
  • @GSerg, ah I see as in implementers of the language not developers using the language. Oh man – Michael Riley Jul 09 '21 at 19:12

1 Answers1

-1

I get the sense you're convoluting a lot of assumptions and concerns with static, structs, reflection, etc. and losing track of where you want to go. You've apparently tried to solve the wrong problems the wrong way. But I'll address your questions one at a time.

I am not sure if the method is just called or is an actual instance of the class created using the default constructor?

Why would you think that? You didn't post the code of the test methods but I can assure you that InvokeMember actually invokes the member.

I started noticing that private attributes of this class set during one call were not there during another call to a different static function that needed them.

Probably because the test methods create a new testResultInfo each time, but without the code it's impossible to know. But I don't see why that is a problem. What data do you need to "carry over"? Maybe you need a static testResultInfo property on testSuite that you can reuse within the methods?

Looking into that I learned that I could change my class to inherit from 'Type'

I can't see any reason whatsoever why you'd need to do that or what you think that would solve.

Stop trying top band-aid problems that were created by trying to fix other problems, possibly in the wrong way. Back up, analyze your program and think about where different instances are created? should these test methods magically know about the instance that you've created in the form or should they be given that instance somehow? How should you do that? Should you make it an input parameter? Or a static property of the test suite?

D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • It's not a waste - it's not like we spent hours trying to fix everything - my intent was more to encourage you to take a step back and get back to the basics rather then trying to solve the wrong problem. If you still have concrete problems don't be afraid to ask. – D Stanley Jul 09 '21 at 20:17