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
Automated Property with Getter Only, Can Be Set, Why
Is There a "Between" Function in C#
Show Controls Added Programmatically in Winforms App in Design View
Log Queries Executed by Entity Framework Dbcontext
ASP.NET MVC Razor Render Without Encoding
Static Property Using Inotifypropertychanged. C#
What's the Difference Between Using the Serializable Attribute & Implementing Iserializable
Async Threadsafe Get from Memorycache
How to Make Chrome Headless After I Login Manually
How to Print <Xml Version="1.0"> Using Xdocument
C# Quickest Way to Shift Array
Securing a Password in Source Code