Working with static class in a dynamically loaded third party assembly
I'm in the situation that I have to use an unsigned third party .NET DLL in my signed application. So I decided to load that library dynamically at run-time:
var asm = Assembly.LoadFrom("THIRDPARTYASSEMBLY.DLL");
There is a static class in the DLL which I defined an interface for in my application and used GetUninitializedObject()
to l开发者_如何学运维oad the class:
var obj = FormatterServices.GetUninitializedObject(asm.GetType("NAMESPACE.CLASS")) as IMyInterface;
Although the class I'm trying to load is not abstract (It's a public static
class) I get this error at runtime:
System.MemberAccessException was unhandled: Cannot create an abstract class.
Obviously I can't use CreateInstance
method because the static class doesn't have any constructors.
So what would you suggest? I want to:
- Invoke a
public static
method from that library. (I'm currently usingInvokeMember()
.) - Get a
Custom Type
property. - Handle a few
Custom Events
in my application.
Thanks in advance.
Instead of trying to call the method dynamically, you could try to strong name the third party dll.
You will need a key to strong name the dll with. You could either use the one you are already using for your own dll, or create a new one for this purpose (using sn -k
).
To strong name the already compiled assembly:
- Open a visual studio command prompt (to get the tools into your path).
- Generate il from the assembly:
ildasm ThirdParty.dll /out:ThirdParty.il
- Rename the original ThirdParty.dll to something else.
- Generate a new dll, strong naming it as you do so:
ilasm ThirdParty.il /dll /key=MyKey.snk
This will result in a new ThirdParty.dll
which will be strong named with the key you have specified. You can then add a direct reference to it and call the methods directly as you normally would.
You don't need the uninitialized object if it's just a static class. Once you have gotten the type, eg
Type t = asm.GetType("NAMESPACE.CLASS");
you can get the methods you need with
MethodInfo method = t.GetMethod("MethodName");
//getmethod has some useful overloads
//also GetMethods() returns a MethodInfo[] array containing all methods
then you can call
object result = method.Invoke(null, new object[] { param1, param2, ... } );
There are other ways of doing this as well. You can use delegates to get a function pointer to the method instead of calling invoke.
I'm not sure how to do the eventhandlers, although I'm sure if you browse intellisense under a Type object you should be able to find something. As far as the properties are concerned, generally you only use them for objects, but if you want to use properties on a static class, and you already know the return type in advance, you could create a class to handle it:
public class ExternalProperty<PropertyType>
{
delegate PropertyType GetFunction();
delegate void SetFunction(PropertyType value);
GetFunction GetValue;
SetFunction SetValue;
public ExternalProperty(PropertyInfo externalProperty)
{
MethodInfo getMethod = externalProperty.GetGetMethod();
GetFunction getter = (GetFunction)Delegate.CreateDelegate(typeof(GetFunction), getMethod);
MethodInfo setMethod = externalProperty.GetSetMethod();
SetFunction setter = (SetFunction)Delegate.CreateDelegate(typeof(SetFunction), setMethod);
}
public PropertyType Value
{
get { return GetValue(); }
set
{
SetValue(value);
}
}
}
using this class is very easy if you already know the property type. Say you have a property Name of type string:
ExternalProperty<string> PropName = new ExternalProperty(t.GetProperty("Name"));
string oldName = PropName.Value; //this will call the property's getter
PropName.Value = "new name"; //this will call the property's setter
it has no error checking though so if you try to pass a property of a different type than you specify, or one that can't be found to it, it will break. This also doesn't work for objects, only static classes. Hope that helps.
精彩评论