C# Reflection - Load Assembly and Invoke a Method If It Exists

C# reflection - load assembly and invoke a method if it exists

use reflection to check if it has a method called "CustomType MyMethod(byte[] a, int b)" and call it or throw an exception otherwise

Your current code isn't fulfilling that requirement. But you can pretty easily with something like this:

var methodInfo = t.GetMethod("MyMethod", new Type[] { typeof(byte[]), typeof(int) });
if (methodInfo == null) // the method doesn't exist
{
// throw some exception
}

var o = Activator.CreateInstance(t);

var result = methodInfo.Invoke(o, params);

Is this good enough, or are there better/faster/shorter ways?

As far as I'm concerned this is the best way and there isn't really anything faster per say.

What about constructors, given that these methods are not static - can they simply be ignored?

You are still going to have to create an instance of t as shown in my example. This will use the default constructor with no arguments. If you need to pass arguments you can, just see the MSDN documentation and modify it as such.

How can I use reflection to invoke a method on this internal class that exists in a library?

You can use the InternalsVisibleToAttribute to make the internal class visible to your unit test project.

https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute(v=vs.110).aspx

Correct Way to Load Assembly, Find Class and Call Run() Method

Use an AppDomain

It is safer and more flexible to load the assembly into its own AppDomain first.

So instead of the answer given previously:

var asm = Assembly.LoadFile(@"C:\myDll.dll");
var type = asm.GetType("TestRunner");
var runnable = Activator.CreateInstance(type) as IRunnable;
if (runnable == null) throw new Exception("broke");
runnable.Run();

I would suggest the following (adapted from this answer to a related question):

var domain = AppDomain.CreateDomain("NewDomainName");
var t = typeof(TypeIWantToLoad);
var runnable = domain.CreateInstanceFromAndUnwrap(@"C:\myDll.dll", t.Name) as IRunnable;
if (runnable == null) throw new Exception("broke");
runnable.Run();

Now you can unload the assembly and have different security settings.

If you want even more flexibility and power for dynamic loading and unloading of assemblies, you should look at the Managed Add-ins Framework (i.e. the System.AddIn namespace). For more information, see this article on Add-ins and Extensibility on MSDN.

Invoke a method from another assembly

Remember, that 'Invoke' requires a class instance for non-static methods, therefore you should use construction like this:

Type type = myDllAssembly.GetType("TypeName");
type.GetMethod("MyMethod").Invoke(Activator.CreateInstance(type), null);

Complete example with parameterised constructor and method

Class code:

public class MyClass
{
private string parameter;

/// <summary>
/// конструктор
/// </summary>
public MyClass(string parameter)
{
this.parameter = parameter;
}

public void MyMethod(string value)
{
Console.Write("You parameter is '{0}' and value is '{1}'", parameter, value);
}
}

Invokation code:

Type type = typeof(MyClass);
// OR
type = assembly.GetType("MyClass");
type.GetMethod("MyMethod").Invoke(Activator.CreateInstance(type, "well"), new object[] { "played" });

Result:

You parameter is 'well' and value is 'played'

Invoke Method with reflection pass through parameters and receive a return value

Have a look at the signature of MethodInfo.Invoke

public object Invoke(
object obj,
object[] parameters
)

You need to pass the parameters of the method in the parameters object[]. Note that the method returns an object, you just need to cast it to the result type.

A call to TestString should look like this:

var parameters = new object[]{"A string", 10, 'a'};
string result = (string) t.GetMethod("Print").Invoke(t, parameters);

Calling a function from other class using Invoke

See Microsoft help here You can call m.Invoke. or see this post

In more details

public object Invoke(
object obj,
object[] parameters
)

and

Type magicType = Type.GetType("MagicClass");
ConstructorInfo magicConstructor = magicType.GetConstructor(Type.EmptyTypes);
object magicClassObject = magicConstructor.Invoke(new object[]{});

// Get the ItsMagic method and invoke with a parameter value of 100

MethodInfo magicMethod = magicType.GetMethod("ItsMagic");
object magicValue = magicMethod.Invoke(magicClassObject, new object[]{100});

Load assembly from Path

Unfortunately, you won't be able to bypass the GAC - Assembly.LoadFrom(), Assembly.LoadFile(), and even loading it into a byte array and using Assembly.Load(byte[]) will all check the GAC first for an assembly with the same identity, and load it instead.

You used to be able to do what you want in .net 1.1, but since 2.0, the GAC is checked first. See How the Runtime Locates Assemblies - note that step 3 is check the GAC, before probing directories (even if you you fully specified it)

If you want to load one up for Reflection (examining the assembly, rather than running it), you can use Assembly.ReflectionOnlyLoadFrom()

File not found after I just successfully loaded assembly

After some more investigation, it seems like the file was already loaded by another process/assembly perhaps. Changing from Reflection.LoadFile() to Reflection.LoadFrom() resolves the issue.



Related Topics



Leave a reply



Submit