What would be the way to call some method by name, like "Method1", if I've got an Object and it's Type?
I want to do something like this:
Object o;
Type t;
// At this point I know, that 'o' actually has
// 't' as it's type.
// And I know that 't' definitely has a public method 'Method1'.
// So, I want to do something like:
Reflection.CallMethodByName(o, "Method1");
Is this somehow possible? I do realize that this would be slow, it's inconvenient, but unfortunately I've got no other ways to implement this in my case.
If the concrete method name is only known at runtime, you can't use dynamic and need to use something like this:
t.GetMethod("Method1").Invoke(o, null);
This assumes, that Method1 has no parameters. If it does, you need to use one of the overloads of GetMethod and pass the parameters as the second parameter to Invoke.
You would use:
// Use BindingFlags for non-public methods etc
MethodInfo method = t.GetMethod("Method1");
// null means "no arguments". You can pass an object[] with arguments.
method.Invoke(o, null);
See MethodBase.Invoke docs for more information - e.g. passing arguments.
Stephen's approach using dynamic will probably be faster (and definitely easier to read) if you're using C# 4 and you know the method name at compile time.
(If at all possible, it would be nicer to make the type involved implement a well-known interface instead, of course.)
The easiest way:
dynamic myObject = o;
myObject.Method1();
Related
I know I can fetch the method info using GetMethods, but I want to know how to do it properly without GetMethods. I have read other SO questions and answers that suggest this is not possible, or suggest just using LINQ instead, but that isn't really an answer to the question.
Consider at the most basic level, a static generic function that takes a single generic parameter.
private static void Test<T>(T val)
{
}
To fetch this method info we can just call Type.GetMethod("Test", BindingFlags.Static | BindingFlags.NonPublic). However if there were some reason we could not use this simple GetMethod signature (perhaps due to multiple overloads), then we need to supply the parameter types. The problem is that I cannot create a parameter type that accurately matches the T val parameter. What's interesting is that I can take the parameters from the method info (fetched with GetMethods) and pass that into GetMethod to get the desired outcome. This means that if it were only possible to create the appropriate generic types (with IsGenericParameter set to true) then I feel like this would be completely possible.
So that means that this is entirely possible in .NET, and only require the creation of the proper type instances. How does one create these type instances? And if they are not possible to create, why aren't they?
I created a simple fiddle to showcase the issue.
It isn't readily available, because the types you need are actually generic type arguments that only exist in the method / parameter definition. For example, in your Test<T>(T val), the parameter type is "the T as defined by Test<T>. You can't construct that, because it isn't composed from anything. The only way to obtain that T is via GetParameters().
Basically, that leaves: the hard way - i.e. manually. For example:
var method1 = typeof(Program).GetMethods(flags).Single(x => x.Name == "Test"
&& x.IsGenericMethodDefinition && x.GetParameters().Length == 1
&& x.GetParameters()[0].ParameterType == x.GetGenericArguments()[0])
.MakeGenericMethod(paramTypes1);
Obviously it is simpler if you know there is only one Test(...) method:
var method = typeof(Program).GetMethod("Test", flags)
.MakeGenericMethod(paramTypes1);
This isn't calling GetMethod but the "other" way to get a generic method definition is to "cast" a method group to a specific type, then call .Method.GetGenericDefinition() on it.
In your example, the method signature you need is Action<object> where object is just a placeholder and can be any type that matches the constraints of your generic method.
var genericMethodDefinition =
((Action<object>)Test<object>).Method.GetGenericMethodDefinition();
You might select a different overload of "Test" that is defined as private static T Test<T>(T val, int counter) by using the following.
var genericMethodDefinition2 =
((Func<object, int, object>)Test<object>).Method.GetGenericMethodDefinition();
Well, I don't think that it is possible.
But other approach (still hard way, I believe that GetMethods would be better):
var method1 =
typeof (Program).GetMember("Test*",
BindingFlags.InvokeMethod |
BindingFlags.NonPublic |
BindingFlags.Static)
.Cast<MethodInfo>()
.Single(
m =>
m.GetGenericArguments().Length == 1 &&
m.GetGenericArguments()[0].IsGenericParameter)
.MakeGenericMethod(paramTypes1);
Of course, you can omit MakeGenericMethod to get exacly the same result as method2.
Why can't I do Class.GetMethod(string) but I can do this.GetType().GetMethod(string)?
I want to do the former because it seems like it would be a lot quicker since I already know what class I want to search in...
GetMethod is a method declared on the Type class... not on the class you're looking at. (In particular, that class could also have a GetMethod method, which would confuse things significantly...)
You can use
typeof(Class).GetMethod(...)
though, rather than getting the type of a specific instance - is that all you were looking for?
EDIT: Note that GetType(string) is only declared on Type and Assembly (and perhaps some other types). The normal Object.GetType() method doesn't have a string parameter.
Because the former is how you would call a static method on the class.
If you want to get the type of a class, just use typeof:
typeof(Class).GetMethod(someString);
Well, you can do either:
typeof (MyClass).GetMethod("MyMethod");
or
MyClass myClass = new MyClass();
myClass.GetType().GetMethod("MyMethod");
Just to add - myClass.GetType().GetMethod("MyMethod") - Is resolved at runtime, where typeof(MyClass).GetMethod("MyMethod") at compile time.
Here is a bit more on it.
Say I have a method that is overloaded such as void PrintInfo(Person) and void PrintInfo(Item), and so on. I try to invoke these methods by passing in an Object.
I'm wondering why it is giving me an error when I do this; aren't all classes inherited from Object? I want to avoid doing an if/switch statement where I check which type the Object is before calling the appropriate method.
What do you guys think is the best approach in this case?
All Persons are objects , but not all objects are Persons. Because of this you can pass a Person to a method that accepts an object but you can't pass an object to a method that requires a Person.
It sounds like you have some common bit of functionality between various objects that you want to use. Given this, it would be best to find either a common ancestor that has all of the functionality that you need, or an interface that they all implement (that again provides everything that you need).
In the case of printing, you may just need the ToString method. In that case, you can just have the method accept an object and call ToString on it. (That's what many print methods do, such as Console.WriteLine.
You need to understand that because C# is a statically typed language (barring dynamic) the particular overload that is chosen (called overload resolution) is determined at compile time, not run time. That means that the compiler needs to be able to unequivocally determine what type your argument is. Consider:
Object foo;
foo = "String";
foo = 5;
PrintInfo(foo); // Which overload of printinfo should be called? The compiler doesn't know!
There are a few ways to solve this- making foo of type dynamic is one- that will cause the correct overload to be chosen at compile time. The problem with that is that you lose type safety- if you don't have an appropriate overload for that type, your application will still compile but will crash when you try to print the unsupported type's info.
An arguably better approach is to ensure that foo is always of the correct type, rather than just Object.
As #Servy suggests, another approach is to attach the behavior to the type itself. You could, for instance, make an interface IHasPrintInfo:
public interface IHasPrintInfo { String PrintInfo { get; } }
and implement that interface on all items whose info you might print. Then your PrintInfo function can just take an IPrintInfo:
public void PrintInfo(IPrintInfo info) {
Console.WriteLine(info.PrintInfo);
}
here its ambiguate for compiler; compiler can't figure out which version of method (Person/Item) you are intended to call.
I don’t mean overloading. This might include new Types of classes which I haven’t created yet.
EDIT:
I want to create a method which will return a value of the type it gets as a parameter. I can get a parameter of type object, but I don’t want to return it that way and then cast, I want the return-value itself to be of the same type as the parameter.
You could use reflection:
var returnType = typeof(SomeClass).GetMethod("SomeMethodName").ReturnType;
You can create a generic method which returns a type to be determined. As long as you declare your new classes correctly then they should work.
There are a number of ways of doing this, a search for return generic type c# turns up several different techniques of varying complexity. Fundamentally you have:
public T DoStuff<T>()
{
...
}
however, the "..." is the bit that depends on your application.
Based on your updates, the method you want will be something like:
public T MyMethod<T>(T input)
{
// DoSomething
T result = default(T); // Create your instance of T here
return result;
}
Yes, it's called reflection.
This should answer your question: http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.returntype.aspx
You can use generic type and generic methods to do that
C# Generic Methods
Just out of curiosity:
Many LINQ extension methods exist as both generic and non-generic variants, for example Any and Any<>, Where and Where<> etc. Writing my queries I usually use the non-generic variants and it works fine.
What would be the cases when one has to use generic methods?
--- edit ---
P.S.: I am aware of the fact that internally only generic methods are called and the compiler tries to resolve the content of the generic brackets <> during compilation.
My question is rather what are the cases then one has to provide the type explicitly and not to rely on the compiler's intuition?
Always. The C# compiler is smart enough to infer what the type of the method is based on the parameters. This is important when the type is anonymous, and thus has no name.
obj.SomeMethod(123); //these calls are the same
obj.SomeMethod<int>(123);
obj.SomeMethod(new { foo = 123 }); //what type would I write here?!
Edit: To be clear, you are always calling the generic method. It just looks like a non-generic method, since the compiler and Intellisense are smart.
Edit: To your updated question, you would want to be specific if you want to use a type that is not the type of the object you are passing. There are two such cases:
If the parameter implements an interface, and you want to operate on that interface, not the concrete type, then you should specify the interface:
obj.DoSomething<IEnumerable<Foo>>( new List<Foo>() );
If the parameter is implicitly convertible to another type, and you want to use the second type, then you should specify it:
obj.DoSomethingElse<long> ( 123 ); //123 is actually an int, but convertible to long
On the other hand, if you need a cast to do the conversion (or you insert one anyway), then you don't need to specify:
obj.DoYetAnotherThing( (Transformed)new MyThing() ); // calls DoYetAnotherThing<Transformed>
One example I ran into today:
ObjectSet<User> users = context.Users;
var usersThatMatch = criteria.Aggregate(users, (u, c) => u.Where(c));
The above code won't work because the .Where method doesn't return an ObjectSet<User>. You could get around this one of two ways. I could call .AsQueryable() on users, to make sure it's strongly typed as an IQueryable, or I could pass specific type arguments into the Aggregate method:
criteria.Aggregate<Func<User, bool>, IEnumerable<User>>(
PersonSet, (u, c) => u.Where(c));
Another couple of more common examples are the Cast and OfType methods, which have no way to infer what type you want, and in many cases are being called on a non-generic collection in the first place.
In general, the folks that designed the LINQ methods went out of their way to avoid the need to use explicit types in these generic methods, and for the most part you don't need to. I'd say it's best to know it's an option, but avoid doing it unless you find it necessary.