A couple of years ago I had a need to automate dialing a RAS connection and retrieving the IP address allocated by the server. I found myself writing a small, rather limited wrapper around the RAS P/Invoke calls. Far from complete, it only covered the functionality I needed for that project. But it was useful, and I kept it around.
Over the years I've had several people contact me to get a copy of that wrapper to save them time and effort, so to simplify matters, I'll simply attach my RasWrap project here and let google lead people to my blog, rather than to an ancient post on Channel9 where I last mentioned it.
The attachment contains two projects - the RasWrap project itself containing the P/Invoke signatures and wrapper classes to facilitate use, and a RasCaller project, a simple WinForm with example code on using the package.
Both are written for .NET 1.1, though they compiles and should work fine under 2.0.
The project includes a RasPhonebook class for iterating over a PBK file (RAS Phonebook), a RasEntry for retrieving information about an entry, and a RasConnection in order to dial or hang up against a RasEntry.
There is no support for writing new phonebook entries simply because I didn't need that functionality. If you have any problems, do let me know.
When we're working Reflection, we tend to think in different terms than we do when we're actually calling methods. There's an extra level of abstraction in everything we do. Translating between these levels of abstraction isn't always easy or intuitive, so I'll try to go over some common paths, using this following class definition for my examples:
using System.Reflection;
public delegate void MyDelegate();
public class MyClass
{
public void MyMethod() { }
private void MyPrivateMethod() { }
public static void MyStaticMethod() { }
public int MyField;
public int MyProperty
{
get { return MyField; }
set { MyField = value; }
}
}
Concrete -> Reflection
1. Objects
MyClass myObject = new MyClass();
Type myType = myObject.GetType();
2. Classes
Type myType = typeof(MyClass);
Note: The examples from now on will assume we have the myObject and myType variables as defined above.
3. Public Instance Methods
MethodInfo method = myType.GetMethod("MyMethod");
4. Private Instance Methods
MethodInfo privMethod = myType.GetMethod("MyPrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance );
5. Static Methods
MethodInfo statMethod = myType.GetMethod("MyStaticMethod", BindingFlags.Public | BindingFlags.Static);
6. Fields
FieldInfo fi = myType.GetField("MyField");
Note: For static or non-public fields, overloads exist similar to those for methods above.
7. Properties (with their associated Get/Set methods)
PropertyInfo pi = myType.GetProperty("MyProperty");
MethodInfo getMethod = pi.GetGetMethod();
MethodInfo setMethod = pi.GetSetMethod();
Note: For static or non-public properties, overloads exist similar to those for methods above.
8. Delegates
MyDelegate del = myObject.MyMethod;
MethodInfo mi = d.Method;
Reflection -> Concrete
1. Objects
(note the cast)
MyClass myObj = Activator.CreateInstance(myType) as MyClass;
2. Methods (invoking)
For a static method, we will supply null for the first parameter (the instance).
mi.Invoke(myObj, new object[] {…} );
3. Fields
int value = (int)fi.GetValue(myObj);
4. Properties
Unlike fields, properties can take a set of parameters. Either parameterized properties in VB or indexers in C#.
int value = (int)pi.GetValue(myObj, null);
5. Delegates
Delegate to static method:
MyDelegate del = (MyDelegate) Delegate.CreateDelegate(typeof(MyDelegate), method);
Delegate to instance method:
MyDelegate del = (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate), myObj, method.Name);
Note that there is no syntax to create an instance delegate from a MethodInfo; for some reason we only have a weakly-typed overload that accepts the method name as a string. Only the first overload, for static methods, receives a strongly typed MethodInfo.