I am using reflection to invoke a method from another dll.That method takes a class object as input. How can i call that method.
I tried copying the same class to both dlls and i created an object of that class and passed it. It throws invliad conversion error in complie time itself.
Then i tried to let the function take an object as argument and then tried to cast it to the required class. It is throwing invalid cast exception in runtime.
this is what i tried
Test objTest = new Test("name","type");
Assembly assembly = Assembly.Load("MyProject.Components");
Type dllType = assembly.GetType("MynameSpace.MyClass");
if (dllType != null)
{
MethodInfo m = dllType.GetMethod("MyFunction");
object objdll;
objdll = Activator.CreateInstance(dllType);
object[] args = { objTest };
if ((m != null))
{
strReturnValue += (string)m.Invoke(objdll, args);
}
}
In the second dll the method is like
public string MyFunction(Test obj)
My problem is that Class Test is in
the other assembly(the classes are in
two different assemblies)
You have a bit of a design problem. You have an assembly (let's call it assembly A) containing the sample reflection code that you posted. You also have a second assembly (let's call it assembly B) that contains MyClass and Test.
The issue is that in your reflection code you are attempting to create an instance of the Test class so that you can pass it as a parameter to MyClass.MyFunction.
You mentioned that you copied the source code for the Test class into assembly A; that will not work. What you've done there is essentially create two different classes with the same name and same structure. Since the two classes are not the same as far as the CLR is concerned, you will get an invalid cast exception if you try to cast one to the other.
Given what you've posted so far, it seems to me that the most straightforward solution for your approach is to have a third assembly (let's call it assembly C) that contains components that are known to both assemblies A and B. Create a class library project in your solution, move the Test class into that project, get rid of any other occurrences of the Test class in the first two projects, and add references in both of the first two projects referencing the new project. Once you've done that, both assembly A and assembly B will be referencing the same class definition for the Test class and the sample code that you've posted will work.
Let me point out something, though. If the code in assembly A doesn't know enough about the code in assembly B in order to instantiate MyClass and call MyFunction directly (rather than through reflection), then how does it know enough about that code to know what parameters to pass? Does MyFunction have a common method signature that assembly A understands? If that's the case, then MyClass should probably implement an interface that assembly A knows about so that assembly A can invoke MyFunction directly, as shown below:
Assembly assembly = Assembly.Load("MyProject.Components");
Type dllType = assembly.GetType("MynameSpace.MyClass");
if (dllType != null)
{
IMyInterface instance = Activator.CreateInstance(dllType) as IMyInterface;
if (instance != null) // check if this object actually implements the IMyInterface interface
{
instance.MyFunction(objTest);
}
}
If that doesn't seem like an approach that you want, then there are other options. Since it seems like you don't want for assembly A to have a direct reference to assembly B, if you keep the Test class inside of assembly B, then there isn't any way for assembly A to have any knowledge of the Test class in order to construct one. In that case, you could use a factory pattern approach, basically so that assembly A knows of some kind of factory object that is capable of instantiating a Test object. Below is an example of an implementation:
I mentioned above about creating a third project. I would still recommend doing so. In my example, I've named mine "MyProject.Common". It contains the following code:
// define a simple factory interface
public interface IFactory
{
object CreateInstance();
}
// and a generic one (hey, why not?)
public interface IFactory<T> : IFactory
{
new T CreateInstance();
}
// define a Factory attribute that will be used to identify the concrete implementation of a factory
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public class FactoryAttribute : Attribute
{
public Type FactoryType { get; set; }
public FactoryAttribute(Type factoryType)
{
this.FactoryType = factoryType;
}
}
The IFactory interfaces and the Factory attribute will be known and understood by the other projects in my solution, since they both reference the MyProject.Common project.
Below is the code contained within my "MyProject.Components" project:
public class Test
{
public string Name { get; set; }
public string Type { get; set; }
public Test(string name, string type)
{
this.Name = name;
this.Type = type;
}
}
public class TestFactory : IFactory<Test>
{
#region IFactory<Test> Members
public Test CreateInstance()
{
return new Test("name", "type");
}
#endregion
#region IFactory Members
object IFactory.CreateInstance()
{
return this.CreateInstance();
}
#endregion
}
public class MyClass
{
// the Factory attribute on the first parameter indicates that the class TestFactory
// should be used as a factory object to construct the argument for this method
public string MyFunction([Factory(typeof(TestFactory))]Test obj)
{
if (obj == null)
return null;
else
return obj.ToString();
}
}
Finally, I've replaced the original reflection code that you posted with the following:
Assembly assembly = Assembly.Load("MyProject.Components");
Type dllType = assembly.GetType("MynameSpace.MyClass");
if (dllType != null)
{
MethodInfo m = dllType.GetMethod("MyFunction");
object objdll;
objdll = Activator.CreateInstance(dllType);
// use the parameter information to construct the arguments
ParameterInfo[] parameters = m.GetParameters();
object[] args;
if (parameters != null && parameters.Length > 0)
{
args = new object[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
// check for factory attributes on the actual parameter
FactoryAttribute[] attributes = parameters[i].GetCustomAttributes(typeof(FactoryAttribute), true) as FactoryAttribute[];
// if no attributes were found, check the parameter type for factory attributes
if (attributes == null || attributes.Length == 0)
attributes = parameters[i].ParameterType.GetCustomAttributes(typeof(FactoryAttribute), true) as FactoryAttribute[];
// if no attributes were found still, then give up
if (attributes == null || attributes.Length == 0)
{
// this parameter has no factory specified,
// so how would this code know how to create the argument for that parameter ???
args[i] = null;
continue; // move on to the next parameter
}
// there should only be one factory attribute, so use the first one
// assumption made here is that all factory classes will have a parameterless constructor
IFactory factory = Activator.CreateInstance(attributes[0].FactoryType) as IFactory;
args[i] = factory.CreateInstance();
}
}
else
// there are no parameters
args = null;
if ((m != null))
{
strReturnValue += (string)m.Invoke(objdll, args);
}
}
If you mean by class object an object that is a Type object then you can just pass the type of the object as the parameter...e.g.
object[] args = {typeof(typeneeded)};
or
object[] args = { assembly.GetType(typeneeded) };
MethodInfo.Invoke() is declared as the following:
public Object Invoke(
Object obj,
Object[] parameters
)
The first parameter specifies the object to work on, the second one specifies the parameters for the function.
I replicated your code in LINQPad, and this works fine:
void Main()
{
string strReturnValue = "";
Test objTest = new Test("name","type");
Type dllType = typeof(MyClass);
if (dllType != null)
{
MethodInfo m = dllType.GetMethod("MyFunction");
object objdll;
objdll = Activator.CreateInstance(dllType);
object[] args = { objTest };
if ((m != null))
{
strReturnValue += (string)m.Invoke(objdll, args);
}
}
}
public class Test
{
public Test(string s1, string s2)
{
}
}
public class MyClass
{
public string MyFunction(Test t)
{
return "";
}
}
You will have to load the Test object the same way you load the MyClass instance, and as Test requires parameters in the constructor, you'll have to use a ConstructorInfo:
Assembly assembly = Assembly.Load(); //assembly of "Test"
Type testType = assembly.GetType("Test");
ConstructorInfo ci = testType.GetConstructor(
BindingFlags.Public | BindingFlags.Instance,
null,
new Type[]{typeof(string), typeof(string)},
null);
Test objTest = ci.Invoke(new object[] { "name", "type" });
now you can use objTest in the code.
Related
I'm using the following code to load an assembly at runtime and then get a reference to a specific method and obviously execute it at the end:
var assemblyLoaded = Assembly.LoadFile(absolutePath);
var type = assemblyLoaded.GetType("CreateContactPlugin.Plugin");
var instance = Activator.CreateInstance(type);
var methodInfo = type.GetMethod("Execute", new Type[] { typeof(System.String)});
if (methodInfo == null)
{
throw new Exception("No such method exists.");
}
Here is the assembly that I'm calling
namespace CreateContactPlugin
{
public class Plugin
{
static bool Execute(string contactName){
bool contactCreated = false;
if (!String.IsNullOrWhiteSpace(contactName))
{
//process
}
return contactCreated;
}
}
}
I can succesfully load the Assembly, the Type. When I highlight the type variable, I see the method listed in the DeclaredMethods array. But when I try to get the Method, it returns always null.
Does somebody see what I might be doing wrong here ?
There's a couple of problems here. First of all the Execute method is static and not public so you need to specify the correct binding flags to get at it.
var methodInfo = type.GetMethod("Execute", BindingFlags.Static | BindingFlags.NonPublic);
However, an alternative (and preferable in my opinion) solution using less reflection and strong typing would be to make your plugin class implement a common interface, that way you can strongly type your instance object. First make a class library with the relevant interfaces in it, for example:
public interface IContactPlugin
{
bool Execute(string contactName);
}
Now your plugin can also reference the same library and becomes this:
namespace CreateContactPlugin
{
public class Plugin : IContactPlugin
{
public bool Execute(string contactName)
{
//snip
}
}
}
And your calling code would now be this:
var assemblyLoaded = Assembly.LoadFile(absolutePath);
var type = assemblyLoaded.GetType("CreateContactPlugin.Plugin");
var instance = Activator.CreateInstance(type) as IContactPlugin;
if (instance == null)
{
//That type wasn't an IContactPlugin, do something here...
}
instance.Execute("name of contact");
The problem is "static" of
static bool Execute(string contactName)
put it as
public bool Execute(string contactName)
I have some cases where I have to call method names from class names.
string scenario1 = "MockScenario1";
string scenario2 = "MockScenario2";
MockScenario1.GetInfo();
MockScenario2.GetInfo();
How can I dynamically use the strings to call method name here like
scenario1.GetInfo()
scenario2.GetInfo()
I tried to find out all options by string and control space to find related options. Any suggestions?
I am tried the below and trying to Get class name generated dynamically
The below code generated method name dynamically
string methodName = "hello";
//Get the method information using the method info class
MethodInfo mi = this.GetType().GetMethod(methodName);
//Invoke the method
// (null- no parameter for the method call
// or you can pass the array of parameters...)
mi.Invoke(this, null);
More clear scenario:
I am trying to send class name as parameter
MockScenario1 and MockScenario2 are class names.
string scenarioCats = "MockScenario1";
string scenarioDogs = "MockScenario2";
GetResult(scenarioCats);
GetResult(scenarioDogs);
public static void GetCatsResult(string scenarioCats){
scenarioCats obj = new scenarioCats();
obj.GetInfo();
}
public static void GetDogsResult(string scenarioDogs){
scenarioDogs obj = new scenarioDogs();
obj.GetInfo();
}
How to create an instance of a type from its string representation:
string scenario1 = "TheNamespace.MockScenario1";
Type theType = this.GetType().Assembly.GetType(scenario1);
var theInstance = (MockScenario1)Activator.CreateInstance(theType);
theInstance.GetInfo();
It will be better if your classes implement a common interface, for example IGetInfoAware, and then you could write a more generic loader:
var theInstance = (IGetInfoAware)Activator.CreateInstance(theType);
Note: you need to provide the full class name for scenario1 and scenario2
See Activator.CreateInstance
EDIT:
As #Georg pointed out, if the type is not declared in the assembly of the context objects, then it is necessary first to get the assembly where the type is hosted:
var theAssembly = (
from Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()
where (assembly.FullName == "TheNamespace.AssemblyName")
select assembly
)
.FirstOrDefault();
if ( theAssembly!= null ){
Type theType = theAssembly.GetType(scenario1);
var theInstance = (IGetInfoAware)Activator.CreateInstance(theType);
theInstance.GetInfo();
}
If for some reason the assembly name is unknown to you, then the type could be resolved like the following:
public Type GetTypeFromString(String typeName)
{
foreach (Assembly theAssembly in AppDomain.CurrentDomain.GetAssemblies())
{
Type theType = theAssembly.GetType(typeName);
if (theType != null)
{
return theType;
}
}
return null;
}
You can use reflection:
Type thisType = this.GetType();
MethodInfo theMethod = thisType.GetMethod(FunctionName);
theMethod.Invoke(this, userParameters);
You could use the command design pattern. So you'd use a hash map to store your string as the key in the hash map, and then your function would be the value of the hashmap. Then when you want to call your function you say hashmap.get ("yourString"). This would return the function that you stored as your value and you could call it from there.
I suggest using Dictionary<String, Action>, where you can put down all the scenarios and their names e.g.
private static Dictionary<String, Action> s_Scenario =
new Dictionary<String, Action>() {
{"MockScenario1", () => MockScenario1.GetInfo()},
{"MockScenario2", () => MockScenario2.GetInfo()},
};
...
s_Scenario["MockScenario1"]();
s_Scenario["MockScenario2"]();
Without giving Namespace to GetType() can return null always (I faced with that problem before adding this answer.), so it should be like this;
As you mentioned, you want to give string as parameter
public void GetCatsResult(string scenarioCats)
{
string item = this.GetType().Namespace + "." + scenarioCats;
// combined class string with the namespace
Type className = Type.GetType(item);
// found the class
MethodInfo m = className.GetMethod("GetInfo");
// get the method from class
object value = m.Invoke(null,null);
// invoke and value will represent the return value.
}
Here is my Scenario class,
class Scenario1
{
public static string GetInfo()
{
return "GetInfo() called, Scenario1";
}
}
Result; (btw GetCatsResult() called at Form_Load and given string which declared as string scenario1 = "Scenario1";)
Hope helps,
If it is for testing you can use PrivateObject:
using Microsoft.VisualStudio.TestTools.UnitTesting;
class Class1
{
public Class1()
{
MyClass myClass = new MyClass();
PrivateObject myClassPrivateObject = new PrivateObject(myClass, new PrivateType(typeof(MyClass)));
myClassPrivateObject.Invoke("MyMethod");
}
}
For testing purposes,
I'm trying to construct a scenario in which I have two different dlls with the same namespace, class and method name.
E.g.
DLL1:
namespace SomeNamespace
{
public class Foo
{
public static string Bar()
{
return "A";
}
}
}
DLL2:
namespace SomeNamespace
{
public class Foo
{
public static string Bar()
{
return "B";
}
}
}
I'm trying to write code which dynamically calls Foo.Bar() in order to get exception of ambiguity.
In the code I have I specifically need to pass the dll name as a parameter, which I want to avoid.
Assembly a = Assembly.LoadFile(dllPath);
Type t = a.GetType(typeName);
MethodInfo method = t.GetMethod(methodName);
var result = new object();
if (method.IsStatic)
{
result = method.Invoke(null, null);
}
else
{
object instance = Activator.CreateInstance(t);
result = method.Invoke(instance, null);
}
Is there a way to casue this exception?
If both assemblies have the same assembly name you can use Type.GetType(string) like this: https://stackoverflow.com/a/6465096/613130, so
Type t = Type.GetType("SomeNamespace.Foo,SomeAssembly");
I don't think there is a .NET method to search for a Type in all the loaded assemblies.
I'm using nBuilder to generate some Testdata for my application.
First I tested it and it worked fine.
An easy Example:
Customer customer = Builder<Customer>
.CreateNew()
.Build();
Creates a Object and fills all Properties automatically.
By Example, if customer Contains the attribute: name, it will fill it with name1
and so on...
Well all this works fine, but I have troubles to do that whole thing dynamically now.
What I'm doing now, is Reflection, I'm iterating through all Entities in my Class and foreach of them there should be generated some Testdata, even lookups and childlists should be filled, but thats not a problem.. My question is, how I'm using the above code with any type?
ANYTYPE object = Builder<ANYTYPE> ...
What I tried:
object entity = null; //The object/Entity
Assembly assembly = Assembly.GetAssembly(typeof(EMI_ERPContext)); //Getting Assembly
Type type = assembly.GetType(entityName); //I know the Type
//entity = Activator.CreateInstance(type); Do I must create an Instance here?
object entity = Builder<dynamic> //The above code.. Tried to put dynamic as Type, but doesnt work
.CreateNew()
.Build();
I tested with a console app (complete here), faking the classes / interfaces / methods of nBuilder.
So this works, but not tried in real context.
The method you could reuse is "TryToReflectBuilder". It could be much less verbose, but I let the "Step by step" code, as it's probably more explicit. ReflectionConsole.Test is used as the "entity to reflect".
namespace ReflectionConsole {
class Program {
static void Main(string[] args)
{
object test = TryToReflectBuilder("ReflectionConsole.Test");
Console.ReadKey();
}
public static object TryToReflectBuilder(string type)
{
//getting the assembly : not same as your way, but... that wasn't a problem for you
var assembly = Assembly.GetAssembly(typeof(Test));
//getting the entityType by name.
var entityType = assembly.GetType(type);
//The interesting (I hope) part is starting (yeah)
//get the Builder<T> type
var builderClassType = typeof(Builder<>);
//create generic argument for Builder<T> will take the type of our entity (always an array)
Type[] args = {entityType};
//pass generic arguments to Builder<T>. Which becomes Builder<entityType>
var genericBuilderType = builderClassType.MakeGenericType(args);
//create a new instance of Builder<entityType>
var builder = Activator.CreateInstance(genericBuilderType);
//retrieve the "CreateNew" method, which belongs to Builder<T> class
var createNewMethodInfo = builder.GetType().GetMethod("CreateNew");
//invoke "CreateNew" from our builder instance which gives us an ObjectBuilder<T>, so now an ObjectBuilder<entityType> (well as an ISingleObjectBuilder<entityType>, but... who minds ;))
var objectBuilder = createNewMethodInfo.Invoke(builder, null);
//retrieve the "Build" method, which belongs to ObjectBuilder<T> class
var buildMethodInfo = objectBuilder.GetType().GetMethod("Build");
//finally, invoke "Build" from our ObjectBuilder<entityType> instance, which will give us... our entity !
var result = buildMethodInfo.Invoke(objectBuilder, null);
//it would be sad to return nothing after all these efforts, no ??
return result;
}
}
public class Builder<T>
{
public static ISingleObjectBuilder<T> CreateNew()
{
Console.WriteLine(string.Format("{0} creating new",typeof(T)));
return new ObjectBuilder<T>();
}
}
public interface ISingleObjectBuilder<T> : IBuildable<T>
{
}
public interface IObjectBuilder<T> : ISingleObjectBuilder<T>
{
}
public interface IBuildable<T>
{
T Build();
}
public class ObjectBuilder<T> : ISingleObjectBuilder<T>
{
public T Build()
{
Console.WriteLine(string.Format("{0} building myself", typeof(T)));
return Activator.CreateInstance<T>();
}
}
public class Test
{
}
}
I want to create a common unit test function to check all functions based on parameter
for e.g
commonmethod(string methodname,string paramter1,....)
{
....
}
what logic should i write inside this method so that by passing a actual function in parameter methodname and then the common method should execute that function and should return the output.
i am using entity framework for all functions which has been created in my project and now i dont want to create a separate unit test function for each function.just one function should do the job based on different parameters...
is that possible.. ?, if so then please provide me an code for same..
It's never good to have logic in units tests, (switch, if, else, foreach, for, while) and also the kind of common method runner you are suggesting as the test is less readable and possibly introduces hidden bugs.
Many simple, readable, and therefore maintainable tests that are only testing one thing each are far preferable to one test with a lot of complexity.
I would not go for this approach and have an individual unit test for each scenario you want to test, in each method under test. Unit tests are not normally more than a few lines each anyway. And you can still use test frameworks (moq, rhino mocks) and reuse stubs and have some basic helpers to make life easy. Most of all it is important your code is testable to begin with.
You should look at the System.Reflection name space. The MethodInfo object has an Invoke method that allows you to call a method by name.
commonmethod(string methodname,string paramter1,....) { .... }
what logic should i write inside this method so that by passing a actual function
Do you want to pass the actual function, as your description says, or the name of the function, as your method signature says?
You didn't say what your intent is (e.g. what you're trying to accomplish), but if it's to call the passed-in method with a given set of arguments than validate the result somehow, you can just pass in a closure. For instance:
public static void commonmethod (Func<bool> test) {
if (!test())
testFailed();
}
...
Foo.commonmethod( ()=> someobject.foo(2,4) == 6 );
Foo.commonmethod( ()=> someobject.bar("zip", "zap") == "zip zap" );
These are basically callable objects which encapsulate both the method you want to call and the arguments.
#Nilesh if my understanding is correct the following code should be perfect for you. Note that the "CommonMethod" method written below will be applicable only for non static classes with parameterless constructor and non static methods.
The "TestClass" is just for testing purposes.
using System;
using System.Reflection;
using System.Collections;
namespace TestApp
{
public class TestClass
{
public string MyMethod(string param1, string param2)
{
return (param1 + param2);
}
}
public class DynaInvoke
{
///
/// Method to invoke a method inside a class
///
/// Name of a non static class
/// Name of a non static method
/// Parameters required for the method
/// result after execution of the method
public object CommonMethod(string className, string methodName, object[] args)
{
Assembly ass = Assembly.GetCallingAssembly();
object result = InvokeMethodSlow(ass.Location, className, methodName, args);
return result;
}
// this way of invoking a function
// is slower when making multiple calls
// because the assembly is being instantiated each time.
// But this code is clearer as to what is going on
public static Object InvokeMethodSlow(string AssemblyName,
string ClassName, string MethodName, Object[] args)
{
// load the assemly
Assembly assembly = Assembly.LoadFrom(AssemblyName);
// Walk through each type in the assembly looking for our class
foreach (Type type in assembly.GetTypes())
{
if (type.IsClass == true)
{
if (type.FullName.EndsWith("." + ClassName))
{
// create an instance of the object
object ClassObj = Activator.CreateInstance(type);
// Dynamically Invoke the method
object Result = type.InvokeMember(MethodName,
BindingFlags.Default | BindingFlags.InvokeMethod,
null,
ClassObj,
args);
return (Result);
}
}
}
throw (new System.Exception("could not invoke method"));
}
// ---------------------------------------------
// now do it the efficient way
// by holding references to the assembly
// and class
// this is an inner class which holds the class instance info
public class DynaClassInfo
{
public Type type;
public Object ClassObject;
public DynaClassInfo()
{
}
public DynaClassInfo(Type t, Object c)
{
type = t;
ClassObject = c;
}
}
public static Hashtable AssemblyReferences = new Hashtable();
public static Hashtable ClassReferences = new Hashtable();
public static DynaClassInfo
GetClassReference(string AssemblyName, string ClassName)
{
if (ClassReferences.ContainsKey(AssemblyName) == false)
{
Assembly assembly;
if (AssemblyReferences.ContainsKey(AssemblyName) == false)
{
AssemblyReferences.Add(AssemblyName,
assembly = Assembly.LoadFrom(AssemblyName));
}
else
assembly = (Assembly)AssemblyReferences[AssemblyName];
// Walk through each type in the assembly
foreach (Type type in assembly.GetTypes())
{
if (type.IsClass == true)
{
// doing it this way means that you don't have
// to specify the full namespace and class (just the class)
if (type.FullName.EndsWith("." + ClassName))
{
DynaClassInfo ci = new DynaClassInfo(type,
Activator.CreateInstance(type));
ClassReferences.Add(AssemblyName, ci);
return (ci);
}
}
}
throw (new System.Exception("could not instantiate class"));
}
return ((DynaClassInfo)ClassReferences[AssemblyName]);
}
public static Object InvokeMethod(DynaClassInfo ci,
string MethodName, Object[] args)
{
// Dynamically Invoke the method
Object Result = ci.type.InvokeMember(MethodName,
BindingFlags.Default | BindingFlags.InvokeMethod,
null,
ci.ClassObject,
args);
return (Result);
}
// --- this is the method that you invoke ------------
public static Object InvokeMethod(string AssemblyName,
string ClassName, string MethodName, Object[] args)
{
DynaClassInfo ci = GetClassReference(AssemblyName, ClassName);
return (InvokeMethod(ci, MethodName, args));
}
}
}
The following code demonstrates how to use the above code
//Dynamic Invoke Test
DynaInvoke dyn = new DynaInvoke();
object[] args = {"My name is ", "Samar"};
object result = dyn.CommonMethod("TestClass", "MyMethod", args);
Source: Code Project