Reputation: 1797
In my program, we referenced another assembly, and there is an implement instance in that assembly definitely. So we want to invoke its method at run-time. We have known the interface and method name, but the implement instance name is not certainly. How I can invoke method only from interface and method name?
Type outerInterface = Assembly.LoadAssembly("AnotherAssemblyFile").GetTypes()
.Single(f => f.Name == "ISample" && f.IsInterface == true);
Object instance = Activator.CreateInstance(outerInterface);
MethodInfo mi = outerInterface.GetMethod("SampleMethod");
var result = mi.Invoke(instance, new object[]{"you will see me"});
The exception is thrown:
An unhandled exception of type 'System.MissingMethodException' occurred in mscorlib.dll
Additional information: Cannot create an instance of an interface.
The referenced assembly code is here:
namespace AnotherAssembly
{
public interface ISample
{
string SampleMethod(string name);
}
public class Sample : ISample
{
public string SampleMethod(string name)
{
return string.Format("{0}--{1}", name, "Alexsanda");
}
}
}
But the reflection part not work, I am not sure how I can make it work well.
Edit: I don't know the instance name clearly, only know the interface name and method name. But I know there is an implement class from the interface in that assembly definitely.
Upvotes: 1
Views: 1516
Reputation: 10777
Your error message is really clear: you cannot create an instance of an interface. Imagine if you wrote...
var x = new ISample()
... In normal code. It makes no sense at all.
The error stems from these lines of code...
Type outerInterface = Assembly.LoadAssembly("AnotherAssemblyFile").GetTypes()
.Single(f => f.Name == "ISample" && f.IsInterface == true);
Object instance = Activator.CreateInstance(outerInterface);
... In the above listing you find the interface itself and then attempt to instantiate it.
What you really want to do is find a type that implements the interface and instantiate that instead...
Type type = Assembly.Load("AnotherAssembly")
.GetTypes()
.Single(t => t.GetInterfaces().Contains(typeof(ISample)));
ISample instance = (ISample) Activator.CreateInstance(type);
string result = instance.SampleMethod("test");
...
Note how I cast the instance to ISample
-- this removes the need to call GetMethod
.
If you do not already have a reference to the assembly, you can do this:
Type[] types = Assembly
.Load("AnotherAssembly")
.GetTypes();
Type sampleInterface = types
.Single(f => f.Name == "ISample" && f.IsInterface == true);
Type type = types
.Single(t => t.GetInterfaces().Contains(sampleInterface));
object instance = Activator.CreateInstance(type);
MethodInfo method = type.GetMethod("SampleMethod");
string result = (string) method.Invoke(instance, new object[] { "you will see me" });
Upvotes: 3
Reputation: 38179
You cannot instantiate an interface but you can find the class implementing it:
Assembly assembly = Assembly.LoadAssembly("AnotherAssemblyFile");
Type[] assemblyTypes = assembly.GetTypes();
Type ISampleType = assemblyTypes.GetType("NameSpace.ISample");
Type sampleType = assemblyTypes.Single(type =>
(type != ISampleType) && ISampleType.IsAssignableFrom(type));
object instance = Activator.CreateInstance(sampleType);
MethodInfo mi = sampleType .GetMethod("SampleMethod");
var result = mi.Invoke(instance, new object[]{"you will see me"});
Upvotes: 1
Reputation: 236208
You cannot create instance of interface type, because interface is just an API, it's a contract definition and nothing else. Actually if you'll try to instantiate interface, you'll get exception:
System.MissingMethodException: Cannot create an instance of an interface.
So you need to get type which implements your interface and instantiate instance of that type:
var anotherAssemblyTypes = Assembly.LoadAssembly("AnotherAssemblyFile").GetTypes();
// get interface type
Type outerInterface = anotherAssemblyTypes
.Single(t => t.Name == "ISample" && t.IsInterface);
// find class which implements it
Type outerClass = anotherAssemblyTypes
.Single(t => !t.IsInterface && outerInterface.IsAssignableFrom(t));
// instantiate class
dynamic obj = Activator.CreateInstance(outerClass);
string result = obj.SampleMethod("Bob");
Of course you don't have to use dynamic object here. I used it just to test SampleMethod is called.
Upvotes: 1