0

I have a DLL which contains a bunch of classes and methods. I'm calling invoke on methods within the DLL which return values. This works fine if i'm trying to return a single value such as a string or int. Now I've come across a situation where I need to return a struct and use the values from the struct in my test harness.

The DLL its calling is called WebDriver.

Heres the code im calling for the invoke:

var TestDLL = Assembly.LoadFrom(TestDLLString);
Type myClassType = TestDLL.GetType("SeleniumDPS." + testname);
var instance = Activator.CreateInstance(myClassType);

MethodInfo myResultGetter = myClassType.GetMethod("ReturnResult");

try
{
    myResults = (Results)myResultGetter.Invoke(instance, null);

    teststatus = Results.result;
    testResultFile = Results.testFile;
    StartTime = Results.startTime;
    EndTime = Results.endTime;
    TimeElapsed = Results.timeElapsed;
    TestName = Results.testName;
}

Within my test harness I created an exact copy of the struct that I have within my webdriver DLL. Here it is:

public struct Results
{
    public static string testName { get; set; }
    public static int result { get; set; }
    public static DateTime startTime { get; set; }
    public static DateTime endTime { get; set; }
    public static TimeSpan timeElapsed { get; set; }
    public static string testFile { get; set; }
}

So my overall question here is why doesnt the struct called myResult have the same values as the one returned from the method I called? Ive tried debugging the DLL and its returning the struct like its supposed to, so my assumption is that its an error with the code above.

To highlight what I;m trying to do, all im trying to do is retrieve the struct, I'm not really interested in creating multiple structs etc, I just want to be able to use the data contained within the struct I'm returning from the method.

So I played around with the code and if I do:

Object myObject;
myObject = myResultGetter.Invoke(instance, null);

Then when I add myObject to watch in runtime it contains the correct values! But I need to find someway to get these values into my new struct or class (I don't mind which I use)

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Festivejelly
  • 670
  • 2
  • 12
  • 30
  • The code you have given doesn't even compile. Structs must always contain a non-static member. Why do you make the members of your struct static? – Georg Feb 13 '14 at 12:11
  • Another question: Is your WebDriver DLL managed (e.g. written in C#) or unmanaged (as e.g. C)? – Georg Feb 13 '14 at 12:12
  • @Georg it does compile, the code there is a sample of what im doing. I can include the rest of the code but its very long! Lets just assume the code works until the line: myResults = (Results)myResultGetter.Invoke(instance, null); (because it does, ive tested it) – Festivejelly Feb 13 '14 at 12:18
  • @Georg The DLL was written in C# but I cannot import the DLL into my test harness solution because the loading of DLLs is dynamic based on what XML file the user inputs into the test harness. – Festivejelly Feb 13 '14 at 12:20
  • Thus, the DLL is loaded in a separate AppDomain? – Georg Feb 13 '14 at 12:24
  • The DLL is imported at runtime using var TestDLL = Assembly.LoadFrom(TestDLLString); – Festivejelly Feb 13 '14 at 12:27
  • The goal is that the DLL produces a struct, identical to the structure of the one I posted above. What my goal is to be able to retrieve the values of that struct. – Festivejelly Feb 13 '14 at 12:29
  • Structs are tricky in C#, especially when they are members of classes. Without having your complete code, it is hard to help you. – ThunderGr Feb 13 '14 at 12:39
  • Take a look at http://stackoverflow.com/questions/441309/why-are-mutable-structs-evil – ThunderGr Feb 13 '14 at 12:43

2 Answers2

0

You are storing your result data in static fields. Basically, you should never do that and I guess this is also causing the issue here. In fact, your struct is empty and only serves as a container for static fields.

I am assuming you are running the DLL in a separate AppDomain. This other AppDomain has its own set of static variables, thus the static fields of Results in the AppDomain that consumes the code stay untouched and thus, you have the impression that the values are not returned.

So, the solution here is to simply turn the struct properties to instance properties (and adding an appropriate constructor). According to the common coding guidelines, these properties should also be readonly.

Georg
  • 5,626
  • 1
  • 23
  • 44
  • That makes sense, ive made those changes. So now i have a struct called myResults. However what I need to find out now is how I get the result struct im returning from my invoke, into myResults. Because for whatever reason I dont think its returning it properly. – Festivejelly Feb 13 '14 at 12:38
  • Also if i called the function ReturnResults within the DLL it does correctly return the result, so theres no issue with the returning of the method. Its just grabbing it fro the invoke that im struggling with. – Festivejelly Feb 13 '14 at 12:48
0

Okay so I figured this one out for myself.

Instead of using:

myResults = (Results)myResultGetter.Invoke(instance, null);

I used:

object myResults = myResultGetter.Invoke(instance,null);

then I used reflection to "grab" the values I needed from the object:

int myTestResult = (int)myObject.GetType().GetProperty("result").GetValue(myObject);
string myTestName = (string)myObject.GetType().GetProperty("testName").GetValue(myObject);
DateTime myStartTime = (DateTime)myObject.GetType().GetProperty("startTime").GetValue(myObject);
DateTime myEndTime = (DateTime)myObject.GetType().GetProperty("endTime").GetValue(myObject);
TimeSpan myElapsedTime = (TimeSpan)myObject.GetType().GetProperty("elapsedTime").GetValue(myObject);
string myTestFile = (string)myObject.GetType().GetProperty("testFile").GetValue(myObject);

I can then populate a new struct with these values if I wanted to.

Festivejelly
  • 670
  • 2
  • 12
  • 30