Reflection attribute method - c#

I have an asbtract class and I have classes that are devired from it. I have an attribute called PluginEventAttribute that works like so:
[PluginEventAttribute(PluginEvent.Load)]
public void OnLoad()
{
Log("Test Plugin loaded!");
}
I want my code to check if there is a method that uses that attribute, and if so, call it with custom parameters. How can I do that in C# winforms?

You just have to enumerate the instance methods and call the method if it has said attribute. Here's a working example (I hope I got your intent correctly) :
using System;
using System.Reflection;
class Program
{
class MyAttr : Attribute { }
abstract class Base { };
class Derived : Base
{
[MyAttr]
public void foo() { Console.WriteLine("foo"); }
public void bar() { Console.WriteLine("bar"); }
}
static void Main()
{
Base someInstance = new Derived();
foreach (var m in someInstance.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance))
{
if (m.GetCustomAttribute(typeof(MyAttr)) != null)
{
m.Invoke(someInstance, null); // prints "foo"
}
}
Console.ReadLine();
}
}
You may change the null argument in the call to Invoke to the array of arguments you wish to pass to the function. The contents of that array must match the function signature.

This has nothing to do with WinForms. It's all about CLR runtime and its type system.
I don't know any way how you could "just do it".
You can check if a method M has an attribute A only if you have a MethodInfo object that describes that method (methodinfo.GetCustomAttributes())
You can get MethodInfos in several ways, but the easiest and most obvious is to get the Type object and ask it about its methods (type.GetMethod()/type.GetMethods()).
You can get a Type object in several ways too. If you have any object at hand, you can call its GetType() method. Or, you can ask an Assembly object (that describes a DLL or EXE) about the Types it defines. (..)
So, if you have a foo object that someone already created:
call foo.GetType()
loop over type.GetMethods()
call method.GetCustomAttributes(typeof(YourAttribute))
check if it was found
Now if you notice that it as been found, you will end up having a MethodInfo that matches a method with that attribute. The only thing left is to call that method with methodinfo.Invoke and to pass it both parameters and the foo object.
Situation gets tricky if you don't have a foo object that you want to scan for methods. You must get the whole assembly, scan all types, scan all their methods. You end up with matching MethodInfo again. But you don't have any object to call the method found upon. Either that method will need to be static (so callable without target object) or you will need to somehow get matching object, too.

Related

Invoke abstract class method using reflection c#

My external dll design looks like :
class Engineering
{
ProjectsCollection project {get;}
}
abstract class ProjectsCollection
{
public abstract Project Open(string path);
}
I'm able to proceed till getting the method info
MethodInfo info = type.GetMethod("Open");
How to invoke the method "Open"?
Reflection or not, you cannot invoke an abstract method, because there is nothing to invoke. Sure, you can write
info.Invoke(eng.project, new object[] {path});
but it will throw an exception unless eng.project is set to an object of a non-abstract class descendent from ProjectCollection, which implements the Open method:
class ProjectsCollectionImpl : ProjectsCollection {
public Project Open(string path) {
return ...
}
}
Engineering eng = new Engineering(new ProjectsCollectionImpl());
MethodInfo info = type.GetMethod("Open");
var proj = info.Invoke(eng.project, new object[] {path});
Just call Invoke!
info.Invoke(someObject, new object[] {"This is the parameter of the method"});
Simple as that!
The return value of Invoke will be the return value of Open, which should be a Project object.
From the docs:
Invokes the method or constructor represented by the current instance, using the specified parameters.
Oh, and you should know that someObject above is the object that you're calling the method on. You should always make it an instance of a concrete class! Don't give it null!

The call is ambiguous between the following methods or properties (one static and one non-static)

Why am I not allowed to have a static and non-static methods with the same signature?
Let's say I have a class like this
public class TestClass
{
public object thing { get; set; }
public TestClass()
{
}
public TestClass(object thing)
{
this.thing = thing;
}
public static TestClass ConvertTestClass(object thing)
{
return new TestClass(thing);
}
public TestClass ConvertTestClass(object thing)
{
this.thing = thing;
return this;
}
}
and I try to use it like this
public class SomeOtherClass
{
public SomeOtherClass()
{
TestClass tc = TestClass.ConvertTestClass(new object());
TestClass tc2 = new TestClass();
tc2.ConvertTestClass(new object());
}
}
I get the following errors on TestClass.ConvertTestClass(new object());
The call is ambiguous between the following methods or properties: 'TestClass.ConvertTestClass(object)' and 'TestClass.ConvertTestClass(object)'
and these errors on tc2.ConvertTestClass(new object());
The call is ambiguous between the following methods or properties: 'TestClass.ConvertTestClass(object)' and 'TestClass.ConvertTestClass(object)'
Member 'TestClass.ConvertTestClass(object)' cannot be accessed with an instance reference; qualify it with a type name instead
Can the compiler really not tell the difference between the static and non static versions of that method or am I missing something here?
I am not using ReSharper (which seemed to be the root of a similar problem in other questions).
Its giving you an error, so its a safe bet that the compiler can't, or won't, discern between the two methods.
Its probably a bad idea to do this kind of overload anyways, as it's unclear which method you are intending to invoke, but if that isn't enough, the C# 5 specification defines a method signature like this (Section 3.6):
The signature of a method consists of the name of the method, the
number of type parameters and the type and kind (value, reference, or
output) of each of its formal parameters, considered in the order left
to right. For these purposes, any type parameter of the method that
occurs in the type of a formal parameter is identified not by its
name, but by its ordinal position in the type argument list of the
method. The signature of a method specifically does not include the
return type, the params modifier that may be specified for the
right-most parameter, nor the optional type parameter constraints.
It doesn't explicitly mention static, but it also doesn't include it as part of the definition of a "signature". Thus, its fair to assume that by the spec, a method overload cannot differ only in the fact that it is static or instanced.
I'd write this as a comment however it's easier to make this point in a proper editor.
I think you're only thinking about the logic of calling methods on the class externally i.e. from another class. Within the class methods with the same signature only differing by static doesn't make any sense. e.g you have a class with two methods as follows
public class MyClass
{
public static void HellowWorld()
{
Console.WriteLine("Hello World!");
}
public void HellowWorld()
{
Console.WriteLine("Howdy World!");
}
public void Greet()
{
HellowWorld();
}
}
When compiling you'll see as long as one of the methods is commented out it compiles without errors. You should be able to alternate the commented out method and compile the class succesfully. Indicating there's no way of differentiating which method should be called within the scope of the class.
You could argue that within the class you should be forced to use the same syntax to call a static method as you do externally e.g.
MyClass.HelloWorld();
However, this would defy scoping logic used throughout C#, why should you need to specify the class name within a class? I think such a change would also create ambiguity where the was none, and to do so now would of course break a lot of code out there.
I think the compiler logic as it is makes perfect sense.

Why do we need to explicitly call parent constructor in MSIL?

I just spent hours being confused by an NullReferenceException where I thought there shouldn't be one. I was constructing a class like so:
public class MyClass : MyBase<Foo>
{
public MyClass()
{
base.Method(Foo.StaticField);
}
}
where
public class MyBase<T>
{
private SomeObject bar = new SomeObject();
public void Method(object o)
{
this.bar.AnotherMethod(o); // exception thrown here
}
}
Basically my IL was the following:
ctorIl.Emit(OpCodes.Ldarg_0);
ctorIl.Emit(OpCodes.Ldsfld, staticField);
ctorIl.Emit(OpCodes.Box, typeof(FieldType));
ctorIl.Emit(OpCodes.Call, parentMethod);
ctorIl.Emit(OpCodes.Ret);
and I finally figured that it must be that bar was not being instantiated. I constructed my class in C# and compiled it and found the only difference was that the following should be above the IL above:
ctorIl.Emit(OpCodes.Ldarg_0);
ctorIl.Emit(OpCodes.Call, parentCtor);
// as above
With these lines, my code now works as expected.
So my questions are:
Why do we need to explicitly call the base constructor to instantiate fields?
Is there a legitimate use of not calling the base constructor?
...and if not, why does the CLR accept it as a valid program?
because it isn't automatic, and it allows compilers and IL code to decide both when and if to call the base constructor
well, you can actually instantiate types without using any constructors whatsoever... edge case, sure; but allowed
because it is allowed
Note that you can actually emit a simple constructor (including base call) in a single method:
typeBuilder.DefineDefaultConstructor();

Why do we have to explicitly specify "this" when invoking an extension method from within a method of a class being extended?

public class StoreController : Controller
{
public string Index()
{
// implicitly specified instance does not work
//return GetMemberName();
// must specify this explicitly
return this.GetMemberName();
}
}
public static class Utilities
{
public static string GetMemberName(this Controller caller,
[CallerMemberName] string memberName = "")
{
return caller.GetType().FullName + "." + memberName;
}
}
Why do we have to explicitly specify this when invoking an extension method from within a method of a class being extended?
In my mental model, we usually can omit this such as when we initialize fields, for example.
An extension method is technically not a method attached to your class.
yourClass.ExtensionMethod() isn't the same as yourClass.ClassMethod().
Basically, what you are doing is getting a convenient way of doing this:
ExtensionMethod(YourClass yourClass) {
//do something
return yourClass;
}
That is my understanding of an extension method. It's a convenient way of calling a method against a class you can't change. So, that's why you can't just call it without this. It's not a class method.
Extension method is just a syntactic sugar to call a static method. Tthis line of code return this.GetMemberName(); is actually convert to a call to static method like Utilities.GetMemberName(this);
As you can see, you have to send this to the static method and that is the reason why you need this keyword.
Without being present at the design board meeting where this was decided it's hard to say why it's like that.
In this text I use method or instance method in the sense of a function associated with a specific object instance and I use function in a mathematical sense. A function receives a number of arguments and creates a result (which is potentially void)
If we do not consider virtual methods which are more complex because the actual function to be called is determined runtime then any and all method calls are syntactic sugar. If we have two methods defined below
internal static class Extensions {
public static string FooEx(this MyClass self){
return self.ToString();
}
}
internal class MyClass {
public string Bar(){
var s1 = Foo();
var s2 = this.FooEx();
}
private string Foo(){
return ToString();
}
}
Then both will be translated to a function call where the first (and only) argument in both cases will be the object identified by this. If you are doubtful about this then look at the IL produced for any call to an instance method and you will notice there's an extra argument compared to the declaration in code. This argument is the thisreference, which is always passed as the first argument to an instance method.
So in the case of an instance method the compiler still need to determine which object to pass as the first argument to the function. That is exactly the same it has to do if you are calling an extension method without this which also means that can't be the real reason why you have to use this in front of an extension method.
In the compiler for Marvin, a compiler build on top of the Mono compiler I had to do a similar trick as C# does with extension methods and wondered why the specs require the this
The real reason why the compiler enforces you to use this before an extension method is that the specs says so. What the reason behind that decision is would need the attention of some one like #EricLippert who where probably there when they decided on that requirement

Executing a function of an uncasted object

I am implementing a web control that gets an object (as an argument) with a certain function -- lets call it DoStuff() -- the object can belong to different classes, which are all derived from an abstract class -- lets call it SuperClass -- this SuperClass does not have the DoStuff() method.
So my question is: Is there a way in C# to call a method of an Object on runtime if this method exists in the object without having to cast it to the derived classes.
Something like (I know this does not work but I think it expresses better what I would like to accomplish):
if(myObject.Functions["DoStuff"] != null){
myObject.executeFunction("DoStuff");
}
Is this at all possible??
It's possible with reflection, like:
uses System.Reflection
....
public void ExecuteMethod(object thing, string method)
{
Type type = thing.GetType(); //gets the runtime type of the object
MethodInfo mi = type.GetMethod(method); // null if method not found
mi.Invoke(thing, null); //invokes the method on the "thing" object,
//passing null arguments, and returns the result
}
However, in your scenario it would be better (if possible) to create an interface IDoStuff that will have DoStuff method, and make all classes that will be possibly called to do stuff implement it.
That way your code will be simpler and less prone to errors, like this:
public void ExecuteDoStuff(object thingy)
{
if (thingy is IDoStuff)
((IDoStuff)thingy).DoStuff();
else
throw new Exception("thingy cannot do stuff");
}
Well, in C# 4 you could write:
dynamic d = myObject;
d.DoStuff();
That will throw an exception if the DoStuff() method can't be bound, but the binding is only checked at execution time.
It's relatively tricky to find out whether or not that's going to work without just doing it - you could always catch the exception of course, but it's not ideal.
You could try to find it with reflection, but again I don't see that as an idea approach.
The bigger question is why the abstract class doesn't have the DoStuff method, at least as an abstract method. That would be a far better solution.
If only some of the subclasses have the DoStuff method, it would be better to put that into an interface:
public interface IStuffable
{
void DoStuff();
}
Then make the appropriate subclasses implement IStuffable, and you can write:
IStuffable stuffable = myObject as IStuffable;
if (stuffable != null)
{
stuffable.DoStuff();
}
There are a few ways to do so. I start with the recommended ones:
Create an interface wich contains you DoStuff() method an implement it in all your classes. Then cast your object to that interface:
interface IDoStuff {
void DoStuff();
}
// call it on your object
((IDoStuff)object).DoStuff();
Extend your baseclass to contain your DoStuff() Method (if possible)
Use reflection to call the method:
object.GetType().GetMethod("DoStuff").Invoke();

Categories