I am trying a demo for reflection. The assembly I want to reflect in this class goes something like this
namespace DelegatesSampleApplication
{
delegate bool IsPromotable (Employee employee); // Declaration Syntax is similar to that of a method's
class Program
{
public static void Main(string[] args)
{
//code goes here
}
}
class Employee
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public int Salary { get; set; }
public int Experience { get; set; }
public void PromoteEmployees(List<Employee> employeeList, IsPromotable isPromotableObj)
{
/*foreach (Employee employee in employeeList)
{
if (employee.Experience >= 5 && employee.Salary >= 10000) //That's a hard-coded logic that you have developed as a Framework Developer which makes the class itself not reusable
{
Console.WriteLine(" {0} will be promoted in the next R.P. Cycle ", employee.EmployeeName);
}
}
Console.ReadKey();*/
foreach (Employee employee in employeeList)
{
if (isPromotableObj(employee))
{
Console.WriteLine(" {0} will be promoted in the next R.P. Cycle ", employee.EmployeeName);
}
}
Console.ReadKey();
}
}
}
Now the problem I am facing is, I am trying to read from this assembly in my program and trying to invoke the delegate which takes in a class instance as a parameter.
What I am doing is something like this in a different class altogether
namespace ReflectionSample
{
delegate bool empIsPromotable (Object obj);
class Program
{
static void Main(string[] args)
{
Console.WriteLine("***************Loading External assembly*************");
Assembly assembly = Assembly.LoadFrom(#"C:\Users\Chiranjib\Documents\visual studio 2012\Projects\DelegatesSampleApplication\DelegatesSampleApplication\bin\Debug\DelegatesSampleApplication.exe");
Type employeeType = assembly.GetType("DelegatesSampleApplication.Employee"); //Gets the System.Type object for the Employee Class from the just loaded assembly with all it's dependencies
Console.WriteLine("***************Loading External assembly properties*************");
//Setting properties here
Console.WriteLine("***************Creating an array list that will hold these employee instances***************");
List<Object> employeeInstanceList = new List<object>();
employeeInstanceList.Add(employeeInstance);
employeeInstanceList.Add(employeeInstance2);
Console.WriteLine("***************Invoking External assembly methods*************");
var args = new Object[] {
new List<employeeType>(),
(((employeeInstance) => { return true; }))
};
Console.ReadKey();
}
}
}
This throws error. Saying employeeType missing an assembly reference. Also I cannot convert a lambda expression into an object. I cannot directly type cast to (IsPromotable) right ? I am using reflection. So I am supposed not to have a direct access.
How would I be able to access the delegate via reflection ?
Please help me through. Thanks in advance.
IsPromotable is not invokeable, it's simply a delegate definition. Think of it like an interface. It just tells you what the method takes and returns, but does not actually do anything.
You can call PromoteEmployees like this:
PromoteEmployees(new List<Employee>, (employee) => { return employee.Name == "Rob"; });
Any method which matches the signature of IsPromotable is a valid parameter to the method (ie, any method that takes an Employee and returns a bool). Could you elaborate a bit more on what you're trying to do, exactly?
If you just want a list of delegates, you can do this:
GetType().Assembly.GetTypes().Where(t => t.IsSubClassOf(typeof(BaseDelegate)));
Note; this will only return the delegates in your current assembly. You might want to change it to:
typeof(Employee).GetTypes().Assembly.Where(t => t.IsSubClassOf(typeof(BaseDelegate)));
To get all methods in an assembly which are castable to IsPromotable, you can do this:
var delegateMethod = typeof(IsPromotable).GetMethod("Invoke");
var #params = delegateMethod.GetParameters();
var returnType = delegateMethod.ReturnType;
var matchingMethods = typeof(IsPromotable)
.Assembly
.GetTypes()
.SelectMany(t => t.GetMethods())
.Where(m => {
if (m.ReturnType != returnType)
return false;
var currParams = m.GetParameters();
if (currParams.Length != #params.Length)
return false;
for(var i = 0; i < currParams.Length;i++)
if (currParams[i] != #params[i])
return false;
return true;
});
To invoke the method with reflection, you can do this:
var args = new Object[] {
new List<Employee>(),
((IsPromotable)((emp) => { return true; }))
};
var value = employeeType.InvokeMember("PromoteEmployees", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, employeeInstance, args);
Or, you can just pass it a regular method:
var args = new Object[] {
new List<Employee>(),
((IsPromotable)Test)
};
var value = employeeType.InvokeMember("PromoteEmployees", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, employeeInstance, args);
With the method:
private bool Test(Employee emp)
{
return false;
}
Related
I have several static classes in the namespace mySolution.Macros such as
static class Indent{
public static void Run(){
// implementation
}
// other helper methods
}
So my question is how it will be possible to call those methods with the help of reflection?
If the methods where NOT to be static then I could do something like:
var macroClasses = Assembly.GetExecutingAssembly().GetTypes().Where( x => x.Namespace.ToUpper().Contains("MACRO") );
foreach (var tempClass in macroClasses)
{
var curInsance = Activator.CreateInstance(tempClass);
// I know have an instance of a macro and will be able to run it
// using reflection I will be able to run the method as:
curInsance.GetType().GetMethod("Run").Invoke(curInsance, null);
}
I will like to keep my classes static. How will I be able to do something similar with static methods?
In short I will like to call all the Run methods from all the static classes that are in the namespace mySolution.Macros.
As the documentation for MethodInfo.Invoke states, the first argument is ignored for static methods so you can just pass null.
foreach (var tempClass in macroClasses)
{
// using reflection I will be able to run the method as:
tempClass.GetMethod("Run").Invoke(null, null);
}
As the comment points out, you may want to ensure the method is static when calling GetMethod:
tempClass.GetMethod("Run", BindingFlags.Public | BindingFlags.Static).Invoke(null, null);
You could really, really, really optimize your code a lot by paying the price of creating the delegate only once (there's also no need to instantiate the class to call an static method). I've done something very similar, and I just cache a delegate to the "Run" method with the help of a helper class :-). It looks like this:
static class Indent{
public static void Run(){
// implementation
}
// other helper methods
}
static class MacroRunner {
static MacroRunner() {
BuildMacroRunnerList();
}
static void BuildMacroRunnerList() {
macroRunners = System.Reflection.Assembly.GetExecutingAssembly()
.GetTypes()
.Where(x => x.Namespace.ToUpper().Contains("MACRO"))
.Select(t => (Action)Delegate.CreateDelegate(
typeof(Action),
null,
t.GetMethod("Run", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)))
.ToList();
}
static List<Action> macroRunners;
public static void Run() {
foreach(var run in macroRunners)
run();
}
}
It is MUCH faster this way.
If your method signature is different from Action you could replace the type-casts and typeof from Action to any of the needed Action and Func generic types, or declare your Delegate and use it. My own implementation uses Func to pretty print objects:
static class PrettyPrinter {
static PrettyPrinter() {
BuildPrettyPrinterList();
}
static void BuildPrettyPrinterList() {
printers = System.Reflection.Assembly.GetExecutingAssembly()
.GetTypes()
.Where(x => x.Name.EndsWith("PrettyPrinter"))
.Select(t => (Func<object, string>)Delegate.CreateDelegate(
typeof(Func<object, string>),
null,
t.GetMethod("Print", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)))
.ToList();
}
static List<Func<object, string>> printers;
public static void Print(object obj) {
foreach(var printer in printers)
print(obj);
}
}
Class that will call the methods:
namespace myNamespace
{
public class myClass
{
public static void voidMethodWithoutParameters()
{
// code here
}
public static string stringReturnMethodWithParameters(string param1, string param2)
{
// code here
return "output";
}
}
}
Calling myClass static methods using Reflection:
var myClassType = Assembly.GetExecutingAssembly().GetType(GetType().Namespace + ".myClass");
// calling my void Method that has no parameters.
myClassType.GetMethod("voidMethodWithoutParameters", BindingFlags.Public | BindingFlags.Static).Invoke(null, null);
// calling my string returning Method & passing to it two string parameters.
Object methodOutput = myClassType.GetMethod("stringReturnMethodWithParameters", BindingFlags.Public | BindingFlags.Static).Invoke(null, new object[] { "value1", "value1" });
Console.WriteLine(methodOutput.ToString());
Note: I don't need to instantiate an object of myClass to use it's methods, as the methods I'm using are static.
Great resources:
How C# Reflection Works
MethodBase.Invoke Method
I prefer simplicity...
private void _InvokeNamespaceClassesStaticMethod(string namespaceName, string methodName, params object[] parameters) {
foreach(var _a in AppDomain.CurrentDomain.GetAssemblies()) {
foreach(var _t in _a.GetTypes()) {
try {
if((_t.Namespace == namespaceName) && _t.IsClass) _t.GetMethod(methodName, (BindingFlags.Static | BindingFlags.Public))?.Invoke(null, parameters);
} catch { }
}
}
}
Usage...
_InvokeNamespaceClassesStaticMethod("mySolution.Macros", "Run");
But in case you're looking for something a little more robust, including the handling of exceptions...
private InvokeNamespaceClassStaticMethodResult[] _InvokeNamespaceClassStaticMethod(string namespaceName, string methodName, bool throwExceptions, params object[] parameters) {
var results = new List<InvokeNamespaceClassStaticMethodResult>();
foreach(var _a in AppDomain.CurrentDomain.GetAssemblies()) {
foreach(var _t in _a.GetTypes()) {
if((_t.Namespace == namespaceName) && _t.IsClass) {
var method_t = _t.GetMethod(methodName, parameters.Select(_ => _.GetType()).ToArray());
if((method_t != null) && method_t.IsPublic && method_t.IsStatic) {
var details_t = new InvokeNamespaceClassStaticMethodResult();
details_t.Namespace = _t.Namespace;
details_t.Class = _t.Name;
details_t.Method = method_t.Name;
try {
if(method_t.ReturnType == typeof(void)) {
method_t.Invoke(null, parameters);
details_t.Void = true;
} else {
details_t.Return = method_t.Invoke(null, parameters);
}
} catch(Exception ex) {
if(throwExceptions) {
throw;
} else {
details_t.Exception = ex;
}
}
results.Add(details_t);
}
}
}
}
return results.ToArray();
}
private class InvokeNamespaceClassStaticMethodResult {
public string Namespace;
public string Class;
public string Method;
public object Return;
public bool Void;
public Exception Exception;
}
Usage is pretty much the same...
_InvokeNamespaceClassesStaticMethod("mySolution.Macros", "Run", false);
I'm trying to understand how can I use custom attributes to call method passing a parameters
[ExecuteMe("hello", "reflection")]
public void M3(string s1, string s2)
{
Console.WriteLine("M3 s1={0} s2={1}", s1, s2);
}
I'm trying to call this method using this code:
static void Main(string[] args)
{
var assembly= Assembly.LoadFrom("MyLibrary.dll");
foreach (var type in assembly.GetTypes())
{
object act = Activator.CreateInstance(type);
var methodInfos = type.GetMethods().Where(m => m.GetCustomAttributes(typeof(ExecuteMe)).Any());
foreach (var mInfo in methodInfos)
{
//Console.WriteLine(mInfo.Name);
var argument = mInfo.GetParameters();
foreach (var a in argument)
{
Console.WriteLine(a);
// a.RawDefaultValue;
mInfo.Invoke(act, new object[]{a});
}
}
if (type.IsClass)
Console.WriteLine(type.FullName);
}
Console.ReadLine();
}
It doesn't work because "a" is a ParameterInfo and invoke want a Object[].
What am I doing wrong and how do I get those values?
this is my attribute:
public class ExecuteMe : Attribute
{
public object[] args;
public ExecuteMe(params object[] _args)
{
this.args = _args;
}
}`
I've rewritten it a little. You never actually accessed the arguments you gave to your attribute.
namespace StackOverflow
{
using System;
using System.Reflection;
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
public class ExecuteMe : Attribute
{
public object[] Arguments { get; }
public ExecuteMe(params object[] args)
{
this.Arguments = args;
}
}
public class TestSubject
{
[ExecuteMe(5, "Hello")]
[ExecuteMe(7, "World")]
public int Function(int i, string s)
{
Console.WriteLine("Executing TestSubject.Function with parameters {0} and {1}", i, s);
return 42;
}
}
internal static class Program
{
internal static void Main(string[] args)
{
// This could come from another dll, for example
// var assembly = Assembly.LoadFrom("MyLibrary.dll").GetTypes();
var availableTypes = Assembly.GetExecutingAssembly().ExportedTypes;
foreach (var type in availableTypes)
{
foreach (var method in type.GetMethods())
{
foreach (var attribute in method.GetCustomAttributes<ExecuteMe>())
{
var instance = Activator.CreateInstance(type);
method.Invoke(instance, attribute.Arguments);
}
}
}
Console.ReadLine();
}
}
}
This should yield:
To make sure I understand what you're trying to do, if a method has an ExecuteMe attribute, you want to call the method, passing the arguments from the attribute to the method?
I'm going to assume that this is just for experimentation and you already realize that this doesn't guarantee whether the number or type of arguments supplied to the attribute will match the number and type of arguments the method requires. The attribute takes an unlimited number of objects, while the method requires two strings.
The issue that you're seeing is that you're looking at .GetParameters which doesn't tell you anything about the values coming from the attribute. It just describes what the parameters of the method are.
What you need is to get the args property from the attribute and pass those values when you invoke the method.
Just for the sake of illustration I'm going to use a method where the signatures match.
public class ClassWithMethod
{
[ExecuteMe("hello", "reflection")]
public void M3(params object[] args)
{
var strings = args.Where(arg => arg != null).Select(arg => arg.ToString());
Console.WriteLine(string.Join(", ", strings));
}
// Just to verify that we're only invoking methods with the attribute.
public void MethodWithoutAttribute() { }
}
...and in the console app I'm going to read types from the executing assembly just for convenience.
I rearranged a few things but you'll see what's going on:
static void Main(string[] args)
{
var assembly = Assembly.GetExecutingAssembly();
foreach (var type in assembly.GetTypes())
{
var methodInfos = type.GetMethods();
// looking at all the methods, not yet narrowing it down to those
// with the attribute.
foreach (var mInfo in methodInfos)
{
// We don't just want to know if it has the attribute.
// We need to get the attribute.
var executeMeParameter = mInfo.GetCustomAttribute<ExecuteMe>();
// If it's null the method doesn't have the attribute.
// Ignore this method.
if (executeMeParameter == null) continue;
// We don't need to create the instance until we know that we're going
// to invoke the method.
object act = Activator.CreateInstance(type);
// Pass the args property of the attribute (an array of objects)
// as the argument list for the method.
mInfo.Invoke(act, new object[]{executeMeParameter.args});
}
if (type.IsClass)
Console.WriteLine(type.FullName);
}
Console.ReadLine();
}
In this case we're just passing all of the arguments from the attribute. This is the part where it's a little messy. What if args had three string values but the method had a single int parameter?
This part is a little weird. I had to do this because of the params keyword.
mInfo.Invoke(act, new object[]{executeMeParameter.args});
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Another reason why I'm assuming that this is just for experimentation is that if you wanted to use an attribute to determine which method to run and to pass in hard-coded parameters (which itself is something I can't see doing), this would be much easier:
[ExecuteMe]
public void CallM3()
{
M3("Hello", "reflection");
}
public void M3(params object[] args)
{
var strings = args.Where(arg => arg != null).Select(arg => arg.ToString());
Console.WriteLine(string.Join(", ", strings));
}
...and the attribute has no arguments:
public class ExecuteMe : Attribute
{
}
The difference now is that everything is strongly typed and compiles. You don't have to worry about whether the parameters will match up at runtime.
I have a generic class, and an object value where obj.GetType().GetGenericTypeDefinition() == typeof(Foo<>).
class Foo<T>
{
public List<T> Items { get; set; }
}
How do I get the value of Items from obj? Remember, obj is an Object, I can't cast obj as Foo because I don't know what T is.
I was hoping to use reflection for this, but each time I do GetProperty("Items") it returns null. However, if someone knows a good way to do this without reflection, by all means.
Let's say my code looks like this:
//just to demonstrate where this comes from
Foo<int> fooObject = new Foo<int>();
fooObject.Items = someList;
object obj = (object)fooObject;
//now trying to get the Item value back from obj
//assume I have no idea what <T> is
PropertyInfo propInfo = obj.GetType().GetProperty("Items"); //this returns null
object itemValue = propInfo.GetValue(obj, null); //and this breaks because it's null
You should be able to use:
Type t = obj.GetType();
PropertyInfo prop = t.GetProperty("Items");
object list = prop.GetValue(obj);
You will not be able to cast as a List<T> directly, of course, as you don't know the type T, but you should still be able to get the value of Items.
Edit:
The following is a complete example, to demonstrate this working:
// Define other methods and classes here
class Foo<T>
{
public List<T> Items { get; set; }
}
class Program
{
void Main()
{
//just to demonstrate where this comes from
Foo<int> fooObject = new Foo<int>();
fooObject.Items = new List<int> { 1, 2, 3};
object obj = (object)fooObject;
//now trying to get the Item value back from obj
//assume I have no idea what <T> is
PropertyInfo propInfo = obj.GetType().GetProperty("Items"); //this returns null
object itemValue = propInfo.GetValue(obj, null);
Console.WriteLine(itemValue);
// Does not print out NULL - prints out System.Collections.Generic.List`1[System.Int32]
IList values = (IList)itemValue;
foreach(var val in values)
Console.WriteLine(val); // Writes out values appropriately
}
}
#ReedCopsey is absolutely correct, but in case you're really asking the question "How do I fish out the generic details of a type?", here's some "Fun with Reflection":
public void WhatsaFoo(object obj)
{
var genericType = obj.GetType().GetGenericTypeDefinition();
if(genericType == typeof(Foo<>))
{
// Figure out what generic args were used to make this thing
var genArgs = obj.GetType().GetGenericArguments();
// fetch the actual typed variant of Foo
var typedVariant = genericType.MakeGenericType(genArgs);
// alternatively, we can say what the type of T is...
var typeofT = obj.GetType().GetGenericArguments().First();
// or fetch the list...
var itemsOf = typedVariant.GetProperty("Items").GetValue(obj, null);
}
}
Something like this should do the trick:
var foo = new Foo<int>();
foo.Items = new List<int>(new int[]{1,2,3});
// this check is probably not needed, but safety first :)
if (foo.GetType().GetProperties().Any(p => p.Name == "Items"))
{
var items = foo.GetType().GetProperty("Items").GetValue(foo, null);
}
You have to use System.Reflection namespace to execute the program successfully.
This program gives you Property Name and Value of any Generic Class
You can check this code fiddle on C# Online Rexter Tool Compiler at
using System;
using System.Reflection;
namespace GenericPropertyExample
{
//Declaring a Sample Class
public class class1
{
public string prop1 { get; set; }
public string prop2 { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
//Creating Class Object
class1 objClass1 = new class1 { prop1 = "value1", prop2 = "value2" };
//Passing Class Object to GenericPropertyFinder Class
GenericPropertyFinder<class1> objGenericPropertyFinder = new GenericPropertyFinder<class1>();
objGenericPropertyFinder.PrintTModelPropertyAndValue(objClass1);
Console.ReadLine();
}
//Declaring a Generic Handler Class which will actually give Property Name,Value for any given class.
public class GenericPropertyFinder<TModel> where TModel : class
{
public void PrintTModelPropertyAndValue(TModel tmodelObj)
{
//Getting Type of Generic Class Model
Type tModelType = tmodelObj.GetType();
//We will be defining a PropertyInfo Object which contains details about the class property
PropertyInfo[] arrayPropertyInfos = tModelType.GetProperties();
//Now we will loop in all properties one by one to get value
foreach (PropertyInfo property in arrayPropertyInfos)
{
Console.WriteLine("Name of Property is\t:\t" + property.Name);
Console.WriteLine("Value of Property is\t:\t" + property.GetValue(tmodelObj).ToString());
Console.WriteLine(Environment.NewLine);
}
}
}
}
}
Hey guys ive been struggeling with the same issue with generic typs and finally found the solution that gets the value
--------Small code snippet of the method that does the trick ------------------
public void printFields()
{
// Is the list empty
if (this.list_.Count == 0)
{
//Y => Forced exit no object info
return;
}
try
{
// Get first item from list
T item = this.list_[0];
// Get the type of object
//**Type thisType = item.GetType();
// Get array of all fields
FieldInfo[] thisFieldInfo = item.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
// Loop through all fields and show its info
for (int ix = 0; ix < thisFieldInfo.Length; ix++)
{
// Get Field value
String strVal = thisFieldInfo[ix].GetValue(item).ToString();
// Display item
Console.WriteLine("'{0}' is a {1} and has value {2}", thisFieldInfo[ix].Name, thisFieldInfo[ix].FieldType, strVal);
}
}
catch (SecurityException e)
{
Console.WriteLine("Exception: " + e.Message);
}
}
I have several static classes in the namespace mySolution.Macros such as
static class Indent{
public static void Run(){
// implementation
}
// other helper methods
}
So my question is how it will be possible to call those methods with the help of reflection?
If the methods where NOT to be static then I could do something like:
var macroClasses = Assembly.GetExecutingAssembly().GetTypes().Where( x => x.Namespace.ToUpper().Contains("MACRO") );
foreach (var tempClass in macroClasses)
{
var curInsance = Activator.CreateInstance(tempClass);
// I know have an instance of a macro and will be able to run it
// using reflection I will be able to run the method as:
curInsance.GetType().GetMethod("Run").Invoke(curInsance, null);
}
I will like to keep my classes static. How will I be able to do something similar with static methods?
In short I will like to call all the Run methods from all the static classes that are in the namespace mySolution.Macros.
As the documentation for MethodInfo.Invoke states, the first argument is ignored for static methods so you can just pass null.
foreach (var tempClass in macroClasses)
{
// using reflection I will be able to run the method as:
tempClass.GetMethod("Run").Invoke(null, null);
}
As the comment points out, you may want to ensure the method is static when calling GetMethod:
tempClass.GetMethod("Run", BindingFlags.Public | BindingFlags.Static).Invoke(null, null);
You could really, really, really optimize your code a lot by paying the price of creating the delegate only once (there's also no need to instantiate the class to call an static method). I've done something very similar, and I just cache a delegate to the "Run" method with the help of a helper class :-). It looks like this:
static class Indent{
public static void Run(){
// implementation
}
// other helper methods
}
static class MacroRunner {
static MacroRunner() {
BuildMacroRunnerList();
}
static void BuildMacroRunnerList() {
macroRunners = System.Reflection.Assembly.GetExecutingAssembly()
.GetTypes()
.Where(x => x.Namespace.ToUpper().Contains("MACRO"))
.Select(t => (Action)Delegate.CreateDelegate(
typeof(Action),
null,
t.GetMethod("Run", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)))
.ToList();
}
static List<Action> macroRunners;
public static void Run() {
foreach(var run in macroRunners)
run();
}
}
It is MUCH faster this way.
If your method signature is different from Action you could replace the type-casts and typeof from Action to any of the needed Action and Func generic types, or declare your Delegate and use it. My own implementation uses Func to pretty print objects:
static class PrettyPrinter {
static PrettyPrinter() {
BuildPrettyPrinterList();
}
static void BuildPrettyPrinterList() {
printers = System.Reflection.Assembly.GetExecutingAssembly()
.GetTypes()
.Where(x => x.Name.EndsWith("PrettyPrinter"))
.Select(t => (Func<object, string>)Delegate.CreateDelegate(
typeof(Func<object, string>),
null,
t.GetMethod("Print", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)))
.ToList();
}
static List<Func<object, string>> printers;
public static void Print(object obj) {
foreach(var printer in printers)
print(obj);
}
}
Class that will call the methods:
namespace myNamespace
{
public class myClass
{
public static void voidMethodWithoutParameters()
{
// code here
}
public static string stringReturnMethodWithParameters(string param1, string param2)
{
// code here
return "output";
}
}
}
Calling myClass static methods using Reflection:
var myClassType = Assembly.GetExecutingAssembly().GetType(GetType().Namespace + ".myClass");
// calling my void Method that has no parameters.
myClassType.GetMethod("voidMethodWithoutParameters", BindingFlags.Public | BindingFlags.Static).Invoke(null, null);
// calling my string returning Method & passing to it two string parameters.
Object methodOutput = myClassType.GetMethod("stringReturnMethodWithParameters", BindingFlags.Public | BindingFlags.Static).Invoke(null, new object[] { "value1", "value1" });
Console.WriteLine(methodOutput.ToString());
Note: I don't need to instantiate an object of myClass to use it's methods, as the methods I'm using are static.
Great resources:
How C# Reflection Works
MethodBase.Invoke Method
I prefer simplicity...
private void _InvokeNamespaceClassesStaticMethod(string namespaceName, string methodName, params object[] parameters) {
foreach(var _a in AppDomain.CurrentDomain.GetAssemblies()) {
foreach(var _t in _a.GetTypes()) {
try {
if((_t.Namespace == namespaceName) && _t.IsClass) _t.GetMethod(methodName, (BindingFlags.Static | BindingFlags.Public))?.Invoke(null, parameters);
} catch { }
}
}
}
Usage...
_InvokeNamespaceClassesStaticMethod("mySolution.Macros", "Run");
But in case you're looking for something a little more robust, including the handling of exceptions...
private InvokeNamespaceClassStaticMethodResult[] _InvokeNamespaceClassStaticMethod(string namespaceName, string methodName, bool throwExceptions, params object[] parameters) {
var results = new List<InvokeNamespaceClassStaticMethodResult>();
foreach(var _a in AppDomain.CurrentDomain.GetAssemblies()) {
foreach(var _t in _a.GetTypes()) {
if((_t.Namespace == namespaceName) && _t.IsClass) {
var method_t = _t.GetMethod(methodName, parameters.Select(_ => _.GetType()).ToArray());
if((method_t != null) && method_t.IsPublic && method_t.IsStatic) {
var details_t = new InvokeNamespaceClassStaticMethodResult();
details_t.Namespace = _t.Namespace;
details_t.Class = _t.Name;
details_t.Method = method_t.Name;
try {
if(method_t.ReturnType == typeof(void)) {
method_t.Invoke(null, parameters);
details_t.Void = true;
} else {
details_t.Return = method_t.Invoke(null, parameters);
}
} catch(Exception ex) {
if(throwExceptions) {
throw;
} else {
details_t.Exception = ex;
}
}
results.Add(details_t);
}
}
}
}
return results.ToArray();
}
private class InvokeNamespaceClassStaticMethodResult {
public string Namespace;
public string Class;
public string Method;
public object Return;
public bool Void;
public Exception Exception;
}
Usage is pretty much the same...
_InvokeNamespaceClassesStaticMethod("mySolution.Macros", "Run", false);
Following on from my question here, I'm trying to create a generic value equality comparer. I've never played with reflection before so not sure if I'm on the right track, but anyway I've got this idea so far:
bool ContainSameValues<T>(T t1, T t2)
{
if (t1 is ValueType || t1 is string)
{
return t1.Equals(t2);
}
else
{
IEnumerable<PropertyInfo> properties = t1.GetType().GetProperties().Where(p => p.CanRead);
foreach (var property in properties)
{
var p1 = property.GetValue(t1, null);
var p2 = property.GetValue(t2, null);
if( !ContainSameValues<p1.GetType()>(p1, p2) )
return false;
}
}
return true;
}
This doesn't compile because I can't work out how to set the type of T in the recursive call. Is it possible to do this dynamically at all?
There are a couple of related questions on here which I have read but I couldn't follow them enough to work out how they might apply in my situation.
You can avoid reflection on invocation if you are happy to compare based on the statically know types of the properties.
This relies on Expressions in 3.5 to do the one off reflection in a simple manner, it is possible to do this better to reduce effort for extremely nested types but this should be fine for most needs.
If you must work off the runtime types some level of reflection will be required (though this would be cheap if you again cache the per property access and comparison methods) but this is inherently much more complex since the runtime types on sub properties may not match so, for full generality you would have to consider rules like the following:
consider mismatched types to NOT be equal
simple to understand and easy to implement
not likely to be a useful operation
At the point the types diverge use the standard EqualityComparer<T>.Default implementation on the two and recurse no further
again simple, somewhat harder to implement.
consider equal if they have a common subset of properties which are themselves equal
complicated, not really terribly meaningful
consider equal if they share the same subset of properties (based on name and type) which are themselves equal
complicated, heading into Duck Typing
There are a variety of other options but this should be food for thought as to why full runtime analysis is hard.
(note that I have changed you 'leaf' termination guard to be what I consider to be superior, if you want to just use sting/value type for some reason feel free)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Linq.Expressions;
class StaticPropertyTypeRecursiveEquality<T>
{
private static readonly Func<T,T, bool> actualEquals;
static StaticPropertyTypeRecursiveEquality()
{
if (typeof(IEquatable<T>).IsAssignableFrom(typeof(T)) ||
typeof(T).IsValueType ||
typeof(T).Equals(typeof(object)))
{
actualEquals =
(t1,t2) => EqualityComparer<T>.Default.Equals(t1, t2);
}
else
{
List<Func<T,T,bool>> recursionList = new List<Func<T,T,bool>>();
var getterGeneric =
typeof(StaticPropertyTypeRecursiveEquality<T>)
.GetMethod("MakePropertyGetter",
BindingFlags.NonPublic | BindingFlags.Static);
IEnumerable<PropertyInfo> properties = typeof(T)
.GetProperties()
.Where(p => p.CanRead);
foreach (var property in properties)
{
var specific = getterGeneric
.MakeGenericMethod(property.PropertyType);
var parameter = Expression.Parameter(typeof(T), "t");
var getterExpression = Expression.Lambda(
Expression.MakeMemberAccess(parameter, property),
parameter);
recursionList.Add((Func<T,T,bool>)specific.Invoke(
null,
new object[] { getterExpression }));
}
actualEquals = (t1,t2) =>
{
foreach (var p in recursionList)
{
if (t1 == null && t2 == null)
return true;
if (t1 == null || t2 == null)
return false;
if (!p(t1,t2))
return false;
}
return true;
};
}
}
private static Func<T,T,bool> MakePropertyGetter<TProperty>(
Expression<Func<T,TProperty>> getValueExpression)
{
var getValue = getValueExpression.Compile();
return (t1,t2) =>
{
return StaticPropertyTypeRecursiveEquality<TProperty>
.Equals(getValue(t1), getValue(t2));
};
}
public static bool Equals(T t1, T t2)
{
return actualEquals(t1,t2);
}
}
for testing I used the following:
public class Foo
{
public int A { get; set; }
public int B { get; set; }
}
public class Loop
{
public int A { get; set; }
public Loop B { get; set; }
}
public class Test
{
static void Main(string[] args)
{
Console.WriteLine(StaticPropertyTypeRecursiveEquality<String>.Equals(
"foo", "bar"));
Console.WriteLine(StaticPropertyTypeRecursiveEquality<Foo>.Equals(
new Foo() { A = 1, B = 2 },
new Foo() { A = 1, B = 2 }));
Console.WriteLine(StaticPropertyTypeRecursiveEquality<Loop>.Equals(
new Loop() { A = 1, B = new Loop() { A = 3 } },
new Loop() { A = 1, B = new Loop() { A = 3 } }));
Console.ReadLine();
}
}
You need to call the method using reflection, like this:
MethodInfo genericMethod = typeof(SomeClass).GetMethod("ContainSameValues");
MethodInfo specificMethod = genericMethod.MakeGenericMethod(p1.GetType());
if (!(bool)specificMethod.Invoke(this, new object[] { p1, p2 }))
However, your method should not be generic in the first place; it should simply take two object parameters. (Or, if it is generic, it should cache properties and delegates in a generic type)