I know that what i need help with is not called the Parent but that was the closest word i could think of to describe this situation.
This is not actual code i'm using.
I have MainClass which contains object ObjectA.
class MainClass
{
public int mode = 0;
ObjectA obj = new ObjectA();
}
I need to access the mode variable from the ObjectA object. Is this possible? I feel like if i could at least call a method in MainClass from obj i would be all set. Also I'm aware calling MainClass a parent in this sense is incorrect, what is the correct term for both the MainClass and obj in this.
Assuming you are able to change MainClass, I can think of two options:
Add a reference to MainClass when you create an ObjectA instance.
Like you said in your comments, use events.
Using a reference:
class MainClass
{
public int mode = 31416;
ObjectA obj;
public MainClass()
{
obj = new ObjectA(this);
}
public int GetMainClassMode()
{
return mode;
}
public void Test() {
Console.WriteLine("Calling test method inside obj");
obj.Test();
}
}
class ObjectA {
MainClass parent = null;
public ObjectA(MainClass parent)
{
this.parent = parent;
}
public void Test()
{
if (parent != null)
{
Console.WriteLine("Getting mode from 'parent' MainClass");
Console.WriteLine(string.Format("Mode = {0}", parent.GetMainClassMode()));
}
}
}
Using events:
class MainClass
{
public int mode = 31416;
ObjectA obj = new ObjectA();
public MainClass()
{
obj.ValueReturnEvent += HandleValueReturnEvent;
}
public int GetMainClassMode()
{
return mode;
}
// Handle event, return data
private int HandleValueReturnEvent(object sender, EventArgs e)
{
return mode;
}
public void Test() {
Console.WriteLine("Calling test method inside obj");
obj.Test();
}
}
class ObjectA {
// delegate
public delegate int ReturnValueEventHandler(object sender, EventArgs args);
// event
public event ReturnValueEventHandler ValueReturnEvent;
public void Test()
{
// make sure at least one subscriber
if (ValueReturnEvent != null)
{
// note the event is returning a value
var myValue = ValueReturnEvent(this, null);
Console.WriteLine("Getting mode from 'parent' MainClass");
Console.WriteLine(string.Format("Mode = {0}", myValue));
}
}
}
On both cases, you get this output:
Calling test method inside obj
Getting mode from 'parent' MainClass
Mode = 31416
Even though you've got your answer, you could also simply inject it into your ObjectA ... have a constructor that takes an int, and when you create the object pass the mode in and save it in that object.
I find it cleaner that the object uses whatever it needs from its scope, rather than accessing the parent to ask for a variable.
I'm not saying it might not be needed, it just another thought.
You'll have to wire things up to let the child know about the parent for this to work. Something like this:
class ParentClass
{
public int mode = 0;
public ChildClass child = null;
public ParentClass()
{
child = new ChildClass(this);
}
}
class ChildClass
{
public readonly ParentClass parent = null;
public ChildClass (ParentClass parent)
{
this.parent = parent;
}
public int MethodThatReadsParentMode()
{
int mode = parent.mode;
return mode;
}
}
You make field mode public, so I assume it's possible that someone who uses class MainClass do can change this field.
Let's assume program looks like this.
class Program {
var main = new MainClass();
main.mode = 1;
}
Your obj field is private, so Program cannot access it.
So, when someone changed field mode, ObjectA should get new value of field mode.
Possible solution:
class ObjectA {
public int Mode { get; set; }
}
class MainClass {
private obj = new ObjectA();
public int Mode {
get { return this.obj.Mode; }
set { this.obj.Mode = value; }
}
}
There is another option in case field mode belongs to MainCalss.
class ObjectA {
private int mode;
public ObjectA(int mode) {
this.mode = mode;
}
// you can create property instead of method
// I'm not sure how you use this variable, so I just added set method
public void SetMode(int mode) {
this.mode = mode;
}
}
class MainClass {
private int mode = 0;
private obj = new ObjectA();
public int Mode {
get { return this.mode; }
set {
this.obj.SetMode(value);
this.mode = value;
}
}
}
Related
I have a class with a PictureBox created as followed:
public class Tile
{
public PictureBox tilePB = new PictureBox(); //properties don't matter in this case
}
I also have a class GameManager. This is like a referee.
I want to make it so the BackColor of Tile.tilePB can only be edited by Gamemanager and nothing else, and no other class.
I currently have a public PictureBox for Gamemanager (to edit) and a public get function for other classes, but I want to actually make this a valid system instead of what I have right now.
Is this even possible? Please include explenation for the required code.
EDIT: I ran into an issue that I hadn't thought off: class Gamemanager is a static class. I do everything in that class via public static functions. Is this still possible? Since this doesn't work.
You can't do this at compile time, but it can be done at runtime:
public class PictureBox
{
private Color _backColor;
public void SetBackColor(Color color)
{
//getting class type that called this method
var stackTrace = new StackTrace();
var stackFrames = stackTrace.GetFrames();
var callingFrame = stackFrames[1];
var method = callingFrame.GetMethod();
//checking if the class type is GameManager
if (!method.DeclaringType.IsAssignableFrom(typeof(GameManager)))
{
throw new FieldAccessException("Only GameManager can set the background color of a PictureBox!");
}
_backColor = color;
}
public Color BackColor => _backColor;
}
public class Tile
{
public PictureBox tilePB { get; set; }
}
//example GameManager class
public class GameManager
{
public void SetBackground()
{
var someTile = new Tile()
{
tilePB = new PictureBox()
};
var someColor = new Color();
someTile.tilePB.SetBackColor(someColor);
}
}
//example class that may want to set picturebox background color
public class MaliciousClass
{
public void SetBackground()
{
var someTile = new Tile()
{
tilePB = new PictureBox()
};
var someColor = new Color();
someTile.tilePB.SetBackColor(someColor);
}
}
Then somewhere:
var gm = new GameManager();
var mc = new MaliciousClass();
gm.SetBackground(); //this is fine
mc.SetBackground(); //this will throw an exception
If you don't want to throw an exception or you want to do something different when "not authorized" class is trying to access the SetBackColor method then just replace throw new FieldAccessException() with return or whatever you want.
Bare in mind the approach presented here is inefficent and it just presents that in can be done at runtime and nothing more than that.
Not sure if this is exactly what you are looking for, but I made this quick test and it seems to be able to differentiate the calling class:
class Program
{
static void Main(string[] args)
{
Type1 something1 = new Type1();
Type2 something2 = new Type2();
something1.runTest();
something2.runTest();
Console.ReadKey();
}
public class Type1
{
public void runTest()
{
Testing.edit(this);
}
}
public class Type2
{
public void runTest()
{
Testing.edit(this);
}
}
public static class Testing
{
public static void edit(object obj)
{
// This is where you test the calling class to make sure
// it is allowed to edit.
Console.WriteLine(obj.GetType().ToString());
}
}
}
The only way I can think of where you enforce this at compile time, end up being a bit complicated. I don't think you'll want to do this.
You can create an interface with properties/methods for everything that only the GameManager is allowed to do. You can implement this interface in a private inner class below Tile, and make sure the only way this object is created is by passing in a GameManager that receives it. Now, the only way the access can 'leak' is if the GameManager 'gives away' the object.
public class GameManager {
public void AddTile(Tile t, Tile.IManagerHook m) {
m.SomeProperty = "set from manager";
}
}
public class Tile
{
public object SomeProperty { get; private set; }
public Tile(GameManager manager) {
manager.AddTile(this, new ManagerHook(this));
}
public interface IManagerHook {
object SomeProperty {get; set;}
}
private class ManagerHook : IManagerHook {
private Tile _tile;
public ManagerHook(Tile t) {
_tile = t;
}
public object SomeProperty {
get{ return _tile.SomeProperty;}
set { _tile.SomeProperty = value; }
}
}
}
(seems) Simply not possible
After asking several programmers, the way I have coded everything and what I want seems to be simply impossible without immensely complicated code - to the point you are better off refacturing everything. Since class Gamemanager is a static class, there will be no instances of it so you can not check if the 'object' that called it is of class Gamemanager. this also doesn't work since Gamemanager is, agian, static.
I’m working with a state pattern and are wondering how to define variables so they can use in each child class. A protected variable in the abstract parent class may be the right choice, but with this, I’m wondering how to initialize these variables from the main class.
class Main
{
\\Initialize variable "file" here?
\\...
Context tc = new Context(new Step01());
\\...
}
class Context
{
private State ts;
// Constructor
public Context(State st)
{
this.State = st;
}
// Gets or sets the state
public State State
{
get
{
return st;
}
set
{
st = value;
}
}
public void Request()
{
ts.Handle(this);
}
}
abstract class State
{
protected string file = "file";
public abstract void Handle(Context tc);
}
class Step01 : State
{
tc.State = new Step02();
// use variable "file"
}
class Step02 : State
{
tc.State = new Step0x()
// use variable "file"
}
The example is a code snipped and don't work. I hope it helps to explain my question more accurate.
The quantity of child classes (Step0x) varies, so I think it's easier to define the variable only once in the parent class.
Does anybody have an idea how to initialize my variables in the main class?
Thank you.
Define file as constant:
abstract class State
{
protected const string file = "file";
public abstract void Handle();
}
Here is implementation of Step01 and Step02 which are using file:
class Step01 : State
{
public override void Handle(){}
public void PrintFile()
{
Console.WriteLine(string.Format("step1 + {0}", file));
}
}
class Step02 : State
{
public override void Handle(){}
public void PrintFile()
{
Console.WriteLine(string.Format("step2 + {0}", file));
}
}
And here is usage of the Step01 and Step02 classes:
static void Main(string[] args)
{
Step01 step1 = new Step01();
step1.PrintFile();
Step02 step2 = new Step02();
step2.PrintFile();
Console.ReadLine();
}
I have a form that has a button to get a method executed in another class.
Code on the form:
public delegate void CustomPreviewCreate();
public static event CustomPreviewCreate CustomPreviewCreate_Do;
private void CreatePreview()
{
if (CustomPreviewCreate_Do !=null)
{
CustomPreviewCreate_Do();
}
}
This event then gets handled in another class. What I would like to achieve is that I can feed back to the form some form of return value if the method correctly executed.
What I tried so far does not get me the result.
Here is the code:
public void Initialize()
{
SubAsstViewPartControl.CustomPreviewCreate_Do += SubAsstViewPartControl_CustomPreviewCreate_Do;
// this gives me a the compiler error that the return type is wrong
}
private bool SubAsstViewPartControl_CustomPreviewCreate_Do()
{
// do stuff
return false;
}
Is there any direct way to return value from an event handler or I need to use a separate static field to store the event result in?
Update:
Per #Jon's comment, which seemed the simplest to me, I added an answer below demonstrating the simplest approach.
The common approach is to encapsulate your value in the type of EventArgs your event expects. For example, the Framework's CancelEventArgs contains a settable bool Cancel property, allowing each CancelEventHandler to assign a value. The sender can then read the property after the event has been invoked. You could also use a container-like EventArgs class if you want to collect separate values from individual event handlers. For example:
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
public class SingleValueEventArgs : EventArgs
{
public int Value { get; set; }
}
public class MultiValueEventArgs : EventArgs
{
private List<int> _values = new List<int>(); // Private to prevent handlers from messing with each others' values
public IEnumerable<int> Values
{
get { return _values; }
}
public void AddValue(int value) { _values.Add(value); }
}
public class Exposer
{
public event EventHandler<SingleValueEventArgs> WantSingleValue;
public event EventHandler<MultiValueEventArgs> WantMultipleValues;
public void Run()
{
if (WantSingleValue != null)
{
var args = new SingleValueEventArgs();
WantSingleValue(this, args);
Console.WriteLine("Last handler produced " + args.Value.ToString());
}
if (WantMultipleValues != null)
{
var args = new MultiValueEventArgs();
WantMultipleValues(this, args);
foreach (var value in args.Values)
{
Console.WriteLine("A handler produced " + value.ToString());
}
}
}
}
public class Handler
{
private int _value;
public Handler(Exposer exposer, int value)
{
_value = value;
exposer.WantSingleValue += exposer_WantSingleValue;
exposer.WantMultipleValues += exposer_WantMultipleValues;
}
void exposer_WantSingleValue(object sender, SingleValueEventArgs e)
{
Console.WriteLine("Handler assigning " + _value.ToString());
e.Value = _value;
}
void exposer_WantMultipleValues(object sender, MultiValueEventArgs e)
{
Console.WriteLine("Handler adding " + _value.ToString());
e.AddValue(_value);
}
}
class Program
{
static void Main(string[] args)
{
var exposer = new Exposer();
for (var i = 0; i < 5; i++)
{
new Handler(exposer, i);
}
exposer.Run();
}
}
}
Per Jon Skeet's comment, which seemed the simplest to me, the simplest approach seems to be as follows:
public delegate bool CustomPreviewCreate(); // here we declare a return type
public static event CustomPreviewCreate CustomPreviewCreate_Do;
private void CreatePreview()
{
if (CustomPreviewCreate_Do !=null)
{
bool returnval = CustomPreviewCreate_Do();
}
}
And then:
// the method is declared to return the same type
bool SubAsstViewPartControl_CustomPreviewCreate_Do()
{
// do stuff
return true; // return the value of the type declared
}
I am trying to create an event inside my class and handle it from static void main method.my event is triggered by a method named checkAge().But i have got an error like this :
Error1-An object reference is required for the non-static field,
method, or property 'Event.Program.m_AgeChecker(int)
I think i did all prats that i had to do,& i don't know what is the problem.
Code of my first class
class Mahmud
{
public Mahmud()
{
name = "mahmud";
age = 25;
}
private string name;
private int age;
public string Name
{
get{return name;}
set{name=value;}
}
public int Age
{
get { return age; }
set { age = value; }
}
public void checkAge()
{
AgeUpdate(age);
}
public delegate void AgeEventHandler(int mAge);
public event AgeEventHandler AgeUpdate;
}
Code of the second class
static void Main(string[] args)
{
Mahmud m = new Mahmud();
m.AgeUpdate += new Event.Mahmud.AgeEventHandler(m_AgeChecker(m.Age));
m.Age = 16;
m.checkAge();
m.Age = 27;
m.checkAge();
}
private void m_AgeChecker(int A)
{
if (A > 25)
{
Console.WriteLine("!");
}
else
{
Console.WriteLine("ok");
}
}
It looks like you are calling a non-static method from a static method. You will need to make the method static.
static void m_AgeChecker(int A)
{
if (A > 25)
{
Console.WriteLine("!");
}
else
{
Console.WriteLine("ok");
}
}
I'm unsure as to what is the best approach for passing events down the line to parent classes and in need of some feedback.
The example code below tries to illustrate what I want to achieve.
namespace test {
public delegate void TestCompletedEventHandler(object sender,
TestCompletedEventArgs e);
public class Manager {
CarList m_carlist = null;
public CarList Cars {
get { return m_carlist; }
set { m_carlist = value; }
}
public Manager() {
Cars = new CarList(this);
}
public void Report(bool successfull) {
//...
}
}
public class CarList : List<Car> {
protected internal event TestCompletedEventHandler
Car_TestCompleted = null;
protected readonly Manager m_manager = null;
public Manager Manager {
get { return m_manager; }
}
public CarList(Manager manager) {
m_manager = manager;
}
public void Test() {
foreach(Car car in this) {
bool ret = car.Test();
manager.Report(ret);
}
}
public void Add(Car car) {
//Is this a good approach?
car.TestCompleted +=
new TestCompletedEventHandler(Car_TestCompleted_Method);
base.Add(car);
}
private void Car_TestCompleted_Method(object sender,
TestCompletedEventArgs e)
{
if(Car_TestCompleted != null) Car_TestCompleted(sender, e);
}
}
public class Car {
protected internal event TestCompletedEventHandler
TestCompleted = null;
public bool Test() {
//...
if(TestCompleted != null) TestCompleted(this,
new TestCompletedEventArgs())
}
}
public class TestCompletedEventArgs : EventArgs {
//...
}
}
using test;
Manager manager = new Manager();
manager.Cars.Car_TestCompleted +=
new TestCompletedEventHandler (Car_TestCompleted_Method);
manager.Cars.Test();
Another more specific example:
//Contains DataItems and interfaces for working with them
class DataList
{
public List<DataItem> m_dataitems { get; set; }
public TestManager m_testmanager { get; set; }
// ...
}
class DataItem
{
// ...
}
//A manager class for running tests on a DataList
class TestManager
{
public List<TestSource> m_sources { get; set; }
public WorkerManager m_workermanager { get; set; }
// ...
}
//A common interface for Tests
abstract class TestSource
{
public event EventHandler<EventArgs<object>> Completed = null;
protected TestManager m_owner { get; set; }
public abstract void RunAsync();
// ...
}
//A test
class Test1 : TestSource
{
public virtual void RunAsync()
{
//Add commands
//Run workers
//Report progress to DataList and other listeners (like UI)
//Events seem like a bad approach since they need to be forwarded through many levels of abstraction
if(Completed != null) Completed(this, new EventArgs<object>(null));
}
// ...
}
//Manages a number of workers and a queue of commands
class WorkerManager
{
public List<MyWorker> m_workers { get; set; }
public Queue<Command> m_commands { get; set; }
}
//Wrapper for BackgroundWorker
class MyWorker
{
// ...
}
//Async command
interface Command
{
// ...
}
I think you may have just over implemented this a bit... It looks like you are trying to use async operations. Even if you are using sync operations though, typically you'd just use callback methods instead of events in a case like this...
Here is an example of things to change to use callbacks here:
//new delegate
public delegate void CarReportCallback(Car theCar, bool result);
//in the Manager class, make report conform to delegate's signature
public void Report(Car theCar, bool result)
{
//do something, you know which car and what the result is.
}
//in the CarList class pass a reference to the report method in
public void Test()
{
foreach(Car car in this)
{
car.Test(manager.Report);
}
}
//in the Car class use the delegate passed to invoke the reporting
public void Test(CarReportCallback callback)
{
//... do stuff
callback(this, isTestCompleted);
}
It seems reasonable, but I'm not really sure what the use case is and how this would be used.
You've got a strong concept of containment going on, but I'm not really sure why. Also, it's kind of weird that the CarList 'sort of' seems to have ownership of the individual cars.
Additionally, I don't know why Test() on the Car class would both return a result and raise an event. It seems like you're having two different paths to return the same data. And the Manager class seems completely redundant with the CarList class at first glance.
What is the problem you're actually trying to solve here? That might help me with defining a good solution to it.
It wouldn't make sense to just have each car call an event which calls an event on the parent list. I would do it more like this:
namespace test {
public delegate void TestCompletedEventHandler(object sender,
TestCompletedEventArgs e);
public class Manager {
CarList m_carlist = null;
public CarList Cars {
get { return m_carlist; }
set { m_carlist = value; }
}
public Manager() {
Cars = new CarList(this);
}
public void Report(bool successful) {
//...
}
}
public class CarList : List<Car> {
protected readonly Manager m_manager = null;
protected List<Action<object, TestCompletedEventArgs>> delegatesList = new List<Action<object, TestCompletedEventArgs>>();
public Manager Manager {
get { return m_manager; }
}
public CarList(Manager manager) {
m_manager = manager;
}
public void Test() {
foreach(Car car in this) {
bool ret = car.Test();
manager.Report(ret);
}
}
public void Add(TestCompletedEventHandler e) {
foreach (Car car in this) {
car.OnTestCompleted += e;
}
delegatesList.Add(e);
}
public void Add(Car car) {
foreach(Action a in delegatesList)
{
car.OnTestCompleted += a;
}
base.Add(car);
}
}
public class Car {
protected internal event TestCompletedEventHandler OnTestCompleted = null;
public bool Test() {
//...
if (OnTestCompleted != null) OnTestCompleted(this, new TestCompletedEventArgs());
}
}
public class TestCompletedEventArgs : EventArgs {
//...
}
}
using test;
Manager manager = new Manager();
Manager.Cars.Add(new Car());
manager.Cars.Add(new Car());
manager.Cars.Add(new Car());
manager.Cars.Add((sender, args) =>
{
//do whatever...
})
manager.Cars.Test();
manager.Cars.Add(new Car());