get method info into attribute in C# - c#

I want to get method info into attribute in C#.
something like this
Attribute
public class ReflectionAttribute : Attribute
{
public ReflectionAttribute()
{
//reflection things comes here
// for example
// var myMethod = this.GetMethodInfo()
// or something ...
}
}
Class
public class ReflectionTest
{
[Reflection()]
public string SendMessage()
{
return "Hello World";
}
}
Test Class
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
new ReflectionTest().SendMessage();
}
}
I just want to get information about SendMessage method inside attribute when SendMessage method is invoked from Form1.
is it possible? Is there any way in reflection
thank you.

It's not directly possible.
In my case, I want to get MethodInfo into attribute without reflection. However, attribute doesn't work without reflection.
You should use AoP framework (castle, unity..etc).

Related

Using C# reflection to make a Generic List of Controllers derived of the same baseclass

In order to prevent the generation of new identical lines of code, I wanted to retrieve all the fields / properties of the same class and iterate over it in order to execute their functions.
This way, if we need to add more menus to the UIsystem ( MenuControllers) we just need to add the declaration line of the new menu.
Lets write the example code
Main class
public class MenuSystem : UISystem
{
public MainMenuController _mainMenuCtrl;
public PlayerMenuController _playerMenuCtrl;
public StoreMenuController _storeMenuCtrl;
public ...
//This is what I want
private IList<MenuController<BaseMenu>> _menuList;
private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public;
private void InitializeAllMenus()
{
//This is how it looks like now
_mainMenuCtrl.RetrieveMenuInfo();
_playerMenuCtrl.RetrieveMenuInfo();
_storeMenuCtrl.RetrieveMenuInfo();
//****WHAT I WANT TO DO*****
foreach(var menu in _menuList)
{
menu.RetrieveMenuInfo();
}
}
private void DisposeAllMenus()
{
//This is how it looks like now
_mainMenuCtrl.Dispose();
_playerMenuCtrl.Dispose();
_storeMenuCtrl.Dispose();
//****WHAT I WANT TO DO*****
foreach(var menu in _menuList)
{
menu.Dispose();
}
}
}
MenuControllers Definitions
public MainMenuController: MenuController<MainMenu>
{
public Show();
public Hide();
public OnBackButtonClicked();
...
}
public PlayerMenuController : MenuController<PlayerMenu>
{
public Show();
public Hide();
public OnBackButtonClicked();
...
}
...etc
MenuController Class
public abstract class MenuController<T> where T : BaseMenu
{
public void RetrieveMenuInfo() {...}
public void Dispose() {...}
}
I've tried something like this ( and much more to be honest but I think this is enough)
private void FillMenuList()
{
***Retrieving fields, Option 1***
var fieldList = GetType().GetFields(Flags)
.Select(var => var.GetValue(this));
***Retrieving fields, Option 2***
var fieldList = GetType().GetFields(Flags)
.Select(var => var.GetValue(this)).OfType<MenuController<BaseMenu>;
}
OPTION1 of the function above retrieve the fields of the MenuSystem class correctly as IEnumerable<object>
but Option 2 with IEnumerable<MenuController<BaseMenu>> does not retrieve any field.
Our main trouble here is that we cannot fill a list/array with all those types/derived-types to iterate over it.
I really hope its enough with this info. I'm quite newbie using reflection.
I managed to do this before in other parts of the code but with no generics involved
Thanks a lot!
You can try using GetType().GetProperties() on the object, then for each property do item.PropertyType.GetGenericArguments()[0].FullName, this will give you the generic class name. Then you can cast that to the class that you need and get all the fields data.
I hope this helps.

Error when doing simple event\delegate calls when generic class is involved

The following classes
public class PagedItemList<T>
{
public delegate void PageChanged(int newPage);
public event PageChanged PageChangedEvent;
}
public class SomeClass
{
public void SetupWithPagedList<T>(PagedItemList<T> list)
{
list.PageChangedEvent += new PagedItemList<T>.PageChanged(NotifyPageChanged);
}
public void NotifyPageChanged(int newPage) { }
}
Throws the error:
InvalidCastException: Cannot cast from source type to destination type
When I try to add a listener to the event as seen in the example above.
The call to SetupWithPagedList is correctly parametrized:
obj.SetupWithPagedList<Monster>(pagedMonstersList)
I have done events and delegates a lot before, the only difference here is that there is a <T> involved in this class. Has anyone had issues doing events and delegates with templates?
I think your problem in this case is with, the instances. The first question I made when I saw your PagedItemListCode was, why SetupWithPagedList is not an static method, and I checked that you are calling the NotifyPageChanged method in the instance of the class. I do not know the logic behind the problem, but maybe the right way is like this:
public static void SetupWithPagedList<T>(PagedItemList<T> list)
{
list.PageChangedEvent += new PagedItemList<T>.PageChanged(list.NotifyPageChanged);
}
Note that the instance of the class maybe is not the same instance of the object that is passed to the SetupWithPagedList method. Maybe the class is PagedItemList<A> and the method parameter is PagedItemList<Monster>. Maybe the class do not need to be generic. Check it.
EDIT
I tried your code and works perfect:
var p = new PagedItemList<int>();
var sc = new SomeClass();
sc.SetupWithPagedList(p);
p.RaisPageChanged(5);
...
public class PagedItemList<T>
{
public delegate void PageChanged(int newPage);
public event PageChanged PageChangedEvent;
public void RaisPageChanged(int page)
{
if (PageChangedEvent != null)
PageChangedEvent(page);
}
}
public class SomeClass
{
public void SetupWithPagedList<T>(PagedItemList<T> list)
{
list.PageChangedEvent += new PagedItemList<T>.PageChanged(NotifyPageChanged);
}
public void NotifyPageChanged(int newPage)
{
Debug.WriteLine("Page: ",newPage);
}
}
Check it, maybe is something else.

C# Correct way to access parent method

I am new to C# and OOP and have researched many of the similar topics but end up more confused than when I started. I need to be able to call a method in a parent class from a child in another namespace.
Below is a (over) simplified example of what I have now and seems to work, but is this the right/best way?
File Form1.cs:
namespace Test1
{
public partial class Form1 : Form
{
NotTest1.Class1 myClass1 = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Start the child class and pass this parent
myClass1 = new NotTest1.Class1(this);
}
public void Form1Function(String text)
{
textBox1.AppendText(text + Environment.NewLine);
}
private void button1_Click(object sender, EventArgs e)
{
// Do some stuff then call Function1 in myClass1
myClass1.Function1();
}
}
}
File Class1.cs:
namespace NotTest1
{
class Class1 {
Test1.Form1 _parent;
public Class1(Test1.Form1 parent) {
_parent = parent;
}
public void Function1()
{
// Do lots of "stuff"
_parent.Form1Function("Got Here");
}
}
}
Examples appreciated, as I am still trying to learn all of the correct terminology.
Thanks
The best way in Class1.cs use using.
using Test1;
namespace NotTest1
{
class Class1 {
Form1 _parent;
public Class1(Form1 parent) {
_parent = parent;
}
public void Function1()
{
// Do lots of "stuff"
_parent.Form1Function("Got Here");
}
}
}
If Class1 needs to call methods on a Form1 instance, then what you have done is perfectly fine, though I don't see how you have parent and child classes here. What you really a Class1 class that happens to accept a Form1 instance in order to call methods on it.
What you did works fine.
Nonetheless, you may want to explore a bit on Events - this way your Parent class may instantiate a child class and subscribe to its events, and your child class may be completely decoupled from your Parent class.
A very nice, clear example is shown on this thread:
Super-simple example of C# observer/observable with delegates

Error thrown :Form' does not contain a constructor that takes '1' argument. Any help or correction done to sort this error will be very thankful

public void PassValue(string CBA)
{
comboBox1.Text = CBA;
}
public void PassValueA(string CBB)
{
label14.Text = CBB;
}
private void button2_Click(object sender, EventArgs e)
{
Form8 Session = new Form8(comboBox1.Text);
Session.Show();
}
This means that Form8 is missing this:
public Form8(string text) { }
If you opened the code-behind for Form8 I bet you'd see this:
public Form8()
{
// you might even have some code in here
}
BUT, don't get rid of that one, leave it there. The designer will complain next if you do that. Build the one I gave you, and put your code there. Finally, depending on what the overload does, you might want to base one constructor on another, for example:
public Form8() : this("default value") { }
That would call the overloaded constructor from the default constructor and send a default value in for the string.
Now, there is a chance you want it to go the other way. No problem, you could do this:
public Form8(string text) : this() { }
Windows Form Class by default has Parameterless constructor. But You have define a constructor as follows to pass parameter from other forms or class.
public partial class Form8 : Form
{
public Form8(string info) {
//do something
}
}
Does Form8 have a constructor that has one parameter? Something like:
using System.Windows.Forms;
public partial class Form8 : Form
{
public Form8() // This parameterless constructor is required by the WinForms Designer
{
InitializeComponent();
}
public Form8(string someValue) : this() // Constructor chaining
{
// Do something with someValue here
}
}

Trying to call methods between classes created dynamically

I have been trying to work out how to call a method in a different class. Both classes are created dynamically at run-time. Most of the issues I have seen here relate to inheritance, which is different from what I have (I think.)
I am still fairly new to C#, and am trying to test some concepts out.
The first class is something like this:
public class Record
{
CustomPanel _panel;
public void recordFunc(){}
}
The internally created class has something like this:
public class CustomPanel : Panel
{
List<Control> _myControls = new List<Control>;
// _myControls[0] += new EventHandler(myFunc);
public void myFunc(object sender, EventArgs e)
{
// parentClass.recordFunc();
}
}
My objective is to create a Record at run-time from a database call. At that point, it creates a Panel (from my CustomPanel class) that gets added to a FlowLayoutControl. When events are fired from the panel's internal controls, I need to have it update parts of the parent Record class.
Any help is greatly appreciated.
I'm not 100% sure what you're asking, but it seems you want to know how to call a function on a class, when you don't know the class type at runtime, but it could be one or many record types. Is that correct?
If so, a way to cleanly achieve the above is to implement an interface on your derived types and call the interface method. For instance, if you have multiple "Record" classes and don't know the type at runtime, try the following:
public interface IRecord
{
void RecordFunc();
}
public class ARecord : IRecord
{
public void RecordFunc()
{
Console.WriteLine("ARecord.RecordFunc");
}
}
public class AnotherRecord : IRecord
{
public void RecordFunc()
{
Console.WriteLine("AnotherRecord.RecordFunc");
}
}
public class CustomPanel : Panel
{
private IRecord _parentRecord;
// Where parentRecord could be ARecord or AnotherRecord
public class CustomPanel(IRecord parentRecord)
{
_parentRecord = parentRecord;
}
public void MyFunc(object sender, EventArgs e)
{
_parentRecord.RecordFunc();
}
}
If that's not what you're looking for, please clarify.
There is no magic instance of the Record class available from within a CustomPanel just because a Record instance contains a CustomPanel. You'll have to set up such a relationship yourself. E.g.
public class Record
{
CustomPanel _panel;
public CustomPanel panel
{
get { return _panel; }
set { _panel = value; _panel.parent = this; }
}
public void recordFunc(){}
}
public class CustomPanel : Panel
{
public Record parent { get; set; }
public void myFunc(object sender, EventArgs e)
{
parent.recordFunc();
}
}

Categories

Resources