1

So I have a load of instance class's in a namespace I can't change. These are actually exported selenium tests but that detail is not relevant.

Each class has several methods I need to call. Some of the method names are based on the class name. So the methods look like

public void The[Class]Test{ blah blah}

I have code to get all the class's a list of types like this

var tests = (from t in Assembly.GetExecutingAssembly().GetTypes()
    where t.IsClass && t.Namespace == "SeleniumTests"
    select t).ToList();

I then want to loop over these types and execute the method.

I couldn't figure out how to dynamically inherit the test class with a dynamically created object which has an override or alternative methods for the ones I want to call.

I then tried using an expando object and copying over the bits of the class. this didn't work either because some of the properties I need remain in the class instance and are private so can only be set in the method I need to override.

So basically I think I need some way to modify the behavior of class whose name is known at runtime.

EDIT

The method I want to override sets private properties on the instance. The base class looks something like this like this.

 [TestFixture]
    public class Login
    {
        private IWebDriver driver;


        [SetUp]
        public void SetupTest()
        {
            driver = new FirefoxDriver();

        }

        [TearDown]
        public void TeardownTest()
        {

        }

        [Test]
        public void TheLoginTest()
        {

        }

        }

I want to change the FirefoxDriver() to be Chrome or IE drivers.

So I have tried

static void Main(string[] args)
{

    var tests = (from t in Assembly.GetExecutingAssembly().GetTypes()
        where t.IsClass && t.Namespace == "SeleniumTests"
        select t).ToList();


    foreach (var t in tests)
    {

        var test = (dynamic)Activator.CreateInstance(t);

        test.driver = new ChromeDriver();

        test.SetupTest();
        t.GetMethod(String.Format("The{0}Test", t.Name)).Invoke(test, null);
        test.TeardownTest();
 }


    Console.ReadLine();
}

but this won't work because the driver property is private. This means I think I need to override the SetupTest() method. Which would be fine if I could inherit from Login but I am not sure how to do this when the type is only known through reflection.

Kindle Q
  • 944
  • 2
  • 19
  • 28
Jules
  • 1,071
  • 2
  • 18
  • 37
  • Is the question **"How do I call the method on the type?"** and further **"How do I fail over and find the right method because it's not always prefaced with the class name?"** – Mike Perrenoud Apr 10 '13 at 12:40
  • i need to override that method. So i assume i need to inherit from the class on a new dynamically created object. i am ok with finding the right method name. – Jules Apr 10 '13 at 12:45
  • Can you expand with a concret example? In the example you have above, do you want to "override" the `The[Class]Test()` method with a different one? If so, what will be the content of the overridden method? Also - are you then going to call the "overridden" method, or is someone else going to call it indirectly? – Shahar Prish Apr 10 '13 at 13:02
  • edited with an example – Jules Apr 10 '13 at 13:10
  • You can set private properties using reflection if that's all you need to do. – James Apr 10 '13 at 13:14
  • @JamesB thanks, How do i do this? – Jules Apr 10 '13 at 13:20
  • [see here](http://stackoverflow.com/a/1565766/265419) – James Apr 10 '13 at 13:21

1 Answers1

1

You already get and invoke a method via reflection, so setting a field also is no big deal:

foreach (var t in tests)
{
    var test = (dynamic)Activator.CreateInstance(t);

    test.SetupTest();
    t.GetField("driver", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(test, new ChromeDriver());
    t.GetMethod(String.Format("The{0}Test", t.Name)).Invoke(test, null);
    test.TeardownTest();
 }
sloth
  • 99,095
  • 21
  • 171
  • 219