I always get tied up with small things like this... I need to access an objects properties created in class 'Login' from my welcome page class 'Default'. When I try to reference the class so that I may access the object, VS 2010 doesn't list it as available like it normally would, and forcing the request just returns an error.
My Login Class is defined like so:
public abstract class Login : System.Web.UI.UserControl
{
...
private void Login_click(object sender, EventArgs e)
{
MyObject myObject = new MyObject();
myObject.property1 = "something";
}
}
And then i wish to access myObject from my default class, like this:
public class Default : System.Web.UI.Page
{
...
private void Page_load(object sender, System.EventArgs e)
{
string someLocalVar = Login.myObject.property1;
}
}
Where property1 is a property set in the Login class. This does not work, however, and VS doesn't even recognize the Login class; instead it treats it as a reserved word of some sort. These two files are in the same project, so that shouldn't be an issue in the using section. I've accessed variables in this manner between other classes before, just not this time for some reason.
Thanks!
2 things:
Your class is abstract
Your property is probably not static
You don't actually have a property, it's a local variable
You can't instantiate an instance of an abstract class. The point of an abstract class is to create a class with some shared code that other, similar child classes can inherit. Is there a reason your class is abstract?
If your property is not static you have to create an instance of your class in order to access the property. (Which, as I describe above, you can't because it's abstract). If you make your property static, you could then do Login.MyObject without creating an instance.
In the code you supplied, your variable is local to the Login_click method, which means even if you created an instance of your class you wouldn't be able to access it.
I suggest you pick up a C# book and read up on the fundamentals.
There's a number of issues here. First, you're accessing myObject like it's a member of Login, which it isn't. It's a local variable to your Login_click method. Second, you never create an instance of Login in your Default class, so unless it's a static class or you actually create an instance of it, you're not going to be able to access any members of it.
Here's something more like what you want (I think). I've left out your class inheritance for now.
public class Login
{
MyObject object;
public Login() {
object = new MyObject();
object.property1 = "something";
}
}
public class Default {
private void Login_click(object sender, EventArgs e)
{
Login _login = new Login();
string someLocalVar = _login.object.property1;
}
}
Like others have said, you need to more carefully plan this out and strengthen your programming skills before attempting this. This is basic stuff so it shouldn't take an exorbitant amount of time -- don't worry though, we all started here.
You can put your object into a Session variable, and then Cast it back.
//in Login.aspx
MyObject myObject = new MyObject();
myObject.property1 = "something";
Session["UserObject"] = myObject;
//in default.aspx
MyObject obj = (MyObject)Session["UserObject"]
string variable = obj.property1;
Related
Is there any way to let multiple class share the same instance of another class?
So in my c# program i've got three class Gamelogic(A), FPSController(B), and SpawnPlayer(C).
In my case class B and C would use and alter some variables in A, in order to use the variables i'm currently instantiating A in two different classes and then use dot notation to access the variable from the instance of A, but the problem is that after A instantiated in different classes, the change in instance.variable does not share between B and C class at all.
Would static type be a good way of solving this? Or writing a main would be better.
Any suggestions would be appreciated.
There are a few ways. Here is one:
One way would be dependency injection.
You can pass the instance of A along to the constructors of B and C (or to a setter/property of B and C):
A a = new A();
B b = new B(a);
C c = new C(a);
But this doesn't allow you to change the A reference in both objects easily, which seems to be your problem.
One way to easily change the reference, is to wrap the reference in another object somehow.
A nice way to do this could be to create a Context object and pass that context object along to B and C instead of passing A. The context object plays the role as our wrapper. A context object becomes more useful if multiple variables needs to be shared between them (the shared/global state) - see the "Context pattern". Example:
public class Context {
public A a;
public ...other state you want to share...;
public Context(A a) { this.a = a; ... }
}
...
A a = new A();
Context context = new Context(a,...);
B b = new B(context);
C c = new C(context);
Depending on your situation, a static variable might be fine, however. (Or a singleton)
(In some cases passing the A-instance along to the methods of B and C, rather than to their constructor, might be better - then they also always get the current version of a (and might be more thread-safe))
It sounds like you only need to have one instance of each class and pass the data between them. There are several ways to achieve this.
Static classes are one way to go then you'd simply access/set Gamelogic.Property in each of FPSController and SpawnPlayer.
Another way would be to pass the instance of Gamelogic to FPSController and SpawnPlayer when they are created.
However, both of these couple your classes together in ways that might make future changes hard.
A third way would be to make all three classes independent and use events to change values of variables and notify the other classes of changes to these variables. This, however, would probably introduce some lag into your game as there's no guarantee that events are processes in the order you expect.
I can think of two ways, either implement the Singleton pattern for the given classes, which would ensure that only one instance exist at any given time and you can freely use it where ever, will thus achieve your purpose. Check the link by Jon skeet.
If Singleton is not an option then, create a factory, where you pass a key and for given key ensure that only same object is returned, as you can internally store the object in a Dictionary, which would always return same object and you can still create multiple object unlike Singleton
show, this my code.
public interface IMyInterface
{
void SetData(String Data);
}
public partial class Form1 : Form, IMyInterface
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2(this as IMyInterface);
frm.Show();
}
public void SetData(String Data)
{
textBox1.Text = Data;
}
}
public partial class Form2 : Form
{
private IMyInterface frm = null;
public Form2(IMyInterface frm)
{
InitializeComponent();
this.frm = frm;
}
private void button1_Click(object sender, EventArgs e)
{
frm.SetData(textBox1.Text);
}
}
I came across the following situation.
I have a lot of class files in my project, and, as the project was growing, new functions were being created, but without the correct code review. So, we have some duplicated objects (to access the database, like a controller) being created around the same class, but we don't know if it is better to create only one global object or if we should leave them inside the function, because sometimes the code will not reaches that function, so the object will never be created. If it is global, it will be created every time.
Example:
namespace EventWorks.View
{
public partial class Event : System.Web.UI.Page, ISecurityRules
{
protected void btnNew_Click(object sender, EventArgs e)
{
EventController EventCtrl = new EventController();
//some code
}
protected void btnSave_Click(object sender, EventArgs e)
{
EventController EventCtrl = new EventController();
//some code
}
}
}
My question is, where should I create these objects? It's better to create it globally? Or leave it inside the function and let the garbage collector take care of it? Or make a big analysis and check for every file which option is better?
where should I create these objects?
That really depends on the responsibility of the object, the thread-safety considerations (if there are any), and cost of creating such a global member. There is no "yes make it global" solution to all your problems. You should definitely analyze all your members and decide for each one if it is OK to make them globally available and what effects it would have on your system. For example, keeping a DbContext alive in memory as a single instance would be considered bad practice, since it isn't thread-safe.
If you're only worried about unnecessary objects being created, you can always use the Lazy<T> class which will make sure the value is only lazily initialized on the first access:
private readonly Lazy<EventController> eventController = new
Lazy<EventController>(x => new EventController(), isThreadSafe: true);
If used in multiple functions it can be declared on class level like this (thats not global, but class level):
namespace EventWorks.View
{
public partial class Event : System.Web.UI.Page, ISecurityRules
{
EventController _eventController = new EventController();
protected void btnNew_Click(object sender, EventArgs e)
{
_eventController.DoSomething();
}
protected void btnSave_Click(object sender, EventArgs e)
{
_eventController.DoSomething();
}
}
}
It can be initiliased in constructor also, or it can be injected via dependency injection (Constructor, Interface, setter injection), I guess it all depends what you want.
Often a controller keeps some information on the object status. I.e., whether the object is new or whether it has been loaded from a DB, whether it has pending changes or not and so on.
Therefore it seems more logical to have a controller that has the same life-time as the object (it would be created once per object).
If the controller does not store any object dependent stuff, it could be created once per application lifetime. In this case you could make it a singleton.
public class EventController
{
public static readonly EventController Instance = new EventController();
private EventController()
{
// Make constuctor private, so the class cannot be instantiated elsewhere.
}
// Implement functionality here...
}
call it like this:
EventController.Instance.DoSomething();
In my SharePoint 2010 c# / asp.net site, I have a class defined like
namespace PDF_Library.VisualWebPart1
{
public partial class PDF_Library : Usercontrol
{
public static PDF_Library current;
protected void Page_Load(object sender, EventArgs e)
{
current = (PDF_Library)this;
}
}
}
public static class Page_State
{
public static Page is_display()
{
return PDF_Library.current.Page; // didn't work...
}
}
It doesn't have a constructor.
How can I get the reference to the current instance of this class?
I tried something like this in the top
public static PDF_Library current;
Then in a function it had
current = (PDF_Library)this;
But that didn't work...
You need to understand that it does not work this way. Your question is tagged with asp.net - multi-user, multi-threaded environment where multiple instances of PDF_Library user control will be created all the time. It is absolutely uncertain which one of them will be hanging off PDF_Library.current. You need to rethink your design.
More on this: Page instance is disposed of when the request processing is finished. Normally this instance with all its controls and things such as Response, Request, Context etc will be set for garbage collection. Because you keep a reference to a UserControl instance in a static field, all these objects (including Page) will be kept in memory until this current reference is replaced with something else.
It is the fact that you used static in the function that was assinging current that this did not work. static is a method that is not tied to any instance of the class, therefor you can not use this.
Your only options are either make the method non-static or pass in a instance of the class as a parameter to the static function.
From what I can tell you are trying to create a "Singleton Pattern". See the link to the previous MSDN article for examples on how to create a singleton class.
This looks like it will have an instance. If the class is marked as static (which it doesn't appear to be) then you can just reference it by name "PDF_Library". Other wise, use ILSpy or reflector to look at the end result. I bet it has a constructor; just because you don't see one, doesn't mean it isn't there. Override the default ctor and set your instance there.
namespace PDF_Library.VisualWebPart1
{
public partial class PDF_Library : Usercontrol
{
public static PDF_Library Current;
public PDF_Library() : base() {
Current = this;
}
}
}
The problem you might be having with your Page_Load code is that it's being called too late in the lifecycle and that's why your reference call isn't working.
Updated to reflect to my own source
I'm in process of building my first winform application in c# and I'm trying to figure out the best practice for structuring my classes to work smoothly when I use them in my forms.
I have a couple of examples which I will try to explain the best way i can.
When working with get/set variables in a class, the best practice should be something like this:
JobMove.cs
public class JobMove
{
private List<string> jobNames { get; set; }
public string Scanner;
public JobMove()
{
this.Scanner = Properties.Settings.Default.Scanner;
}
public void ListSelected(ListBox lbx)
{
foreach (string jName in this.jobNames)
{
lbx.Items.Add(jName);
}
}
public static List<string> GetCheckedJobs(ListView lw)
{
int countChecked = lw.CheckedItems.Count;
int itemCount = 0;
List<string> jList = new List<string>();
foreach (ListViewItem item in lw.CheckedItems)
{
JobInfo jobInfo = Job.Find(Convert.ToInt32(lw.Items[item.Index].SubItems[1].Text));
jList.Add(jobInfo.Name);
itemCount++;
}
return jList;
}
}
My problem is when I combine this with my forms and I call this, then I would try to do something like this:
MyForm1.cs
public partial class MyForm1 : Form
{
private void btnMoveJobs_Click(object sender, EventArgs e)
{
Properties.Settings.Default.Scanner = cbxScanners.SelectedItem.ToString();
JobMove moveJobs = new JobMove();
frmMoveJobs FrmMoveJobs = new frmMoveJobs();
FrmMoveJobs.ShowDialog();
}
}
MyForm2.cs
public partial class frmMoveJobs : Form
{
public frmMoveJobs()
{
InitializeComponent();
JobMove moveJobs = new JobMove();
lblFrom.Text = moveJobs.Scanner;
moveJobs.ListSelected(lbxJobsToMove);
cbxMjScanners.DataSource = System.Enum.GetValues(typeof(Scanners));
}
}
But when I call MyClass in MyForm2 and I want to call the DoSomethingElse method, then myString will be reset to a null value. And that makes sense to me, but how do I work around this?
I tried to figure out what to use here to get easier around these flaws in my code, but my knowledge is far too weak to just implement an easy solution.
I know I could just store this variable in Settings.settings as an example, but to me that just seems like a real overload for such a simple task.
I might just need a point in the right direction to right on what to do in this situation.
If you do a MyClass myClass = new MyClass(); then indeed - the values are independent and unrelated. If you want to share the MyClass instance then pass the MyClass instance between the forms. Perhaps:
using(var form2 = new Form2()) {
form2.SensibleName = existingMyClassInstance;
form2.ShowDialog();
}
(note the using above btw; when using ShowDialog() it is your job to make sure the form is disposed; it only gets disposed automatically if using Show())
Firstly, they're properties, not variables (the variables are the underlying data source).
Secondly, the whole point of get/set accessors is so you can get and set the value without needing helper methods.
Thirdly, and as to your problem, you're creating a new instance of the class in each form (hinted at by the new keyword) and the value of the property will be whatever it is initialised as on construction of the instance (or not.) i.e. the values of properties are not shared between different instances of the same type.
Think of the mold for a key: I can get multiple instances of the key cut from a "blueprint", but any damage that one suffers won't be reflected by the rest - they're unique in that sense.
If you want the forms to both access the same instance of that type, then you will need to stash the instance somewhere in your code which is accessible to both.
A few options:
Pass in an instance of MyClass in the form2's constructor.
Make MyClass a static property of either Form1 or Form2 and access it via that on the other form.
Make MyClass static (not recommended).
If you want to use the instance of MyClass created in MyForm1 inside of MyForm2, you need to provide it to MyForm2.
Something like this would work:
public partial class MyForm2 : Form
{
public MyForm2(MyClass given)
{
InitializeComponent();
given.DoSomethingElse();
}
}
Easy Solution:
private static string myString { get; set; }
Why: because you initialize the class again when initializing Form2 and it will create a new class. With the "static" keyword you create a property which is the same in all instances of this class.
BUT: please read some books before continuing, this would be the solution to this problem, but the source of many others. Try to understand C# and Forms first, than (or alongside with reading/learning) start coding!
this is because each of your form has a new object of "MyClass".
To achieve what you want to do use a static property... this won't be initialized and gives back the same value for each object of MyClass
it looks like this
public class MyClass {
public static string myString { get; set; }
public void ChangeMyString(string newString)
{
myString = newString;
}
public void DoSomethingElse()
{
MessageBox.Show(myString);
}
}
I'm pretty new to C# and I was trying out a few things. I have a label (named 'newLabel') in the form1.cs. I have a class named 'methods.cs'. In this class I have the method
public static void updateLabel()
what I want to do is:
public static void updateLabel()
{
newLabel.Text = "New Value";
}
but this doesn't work, probably because the method is in methods.cs and the newLabel is in form1.cs.
I had the same problem with declared variables. In the methods.cs I had the variable
int value;
but I couldn't use this variable in form1.cs. I fixed this by doing
public static int value { get; set; }
I have no idea what that did but it works, but I don't know how I can apply this trick with the label.
Could someone help me with this?
Thanks!
You should read up about OOP and encapsulation. Basically you want the form
to access private fields in another object (your class) - this is restricted by encapsulation, that's why you are running into problem - you can get around them by adding those fields and methods to the "public" interface that your class is declaring by making them public properties and methods, i.e in your example:
public int Value {get;set;}
Sometimes composition is used, i.e. in your example since your class is directly accessing the form you could have a form property on your class:
public Form ViewForm {get;set;}
It would be best if you learnt C# from tutorials, but the answer to this particular question lies with something called "scope"
Essentially, scope is the visibility of variables, classes, functions and objects. A variable marked "private" can only be seen within the thing that created it (if it's created inside a function it will always be private and any variables defined inside a function can only be used inside that function). If it's created inside a class only that class can use it.
Variables or functions denoted as public (this can only be done inside a class) can be seen from outside that class. To do that you would invoke myClass.myVariable to access the variable or myClass.myFunction() to access the function.
To denote the visibility of an object you use the keywords "public" or "private". Note: This only applies to variables and functions inside classes (it also applies to other things within classes, such as nested classes and structs, but that's outside the scope of this basic intro).
for example:
class myClass
{
private int myInt;
public void myfunction()
{
myInt = 1;
}
}
This will work, as myInt can be seen by anything inside myClass
class myOtherClass
{
private void myfunction()
{
myClass myObject = new myClass();
myObject.myInt = 2;
}
}
This will not, as myInt is private to myObject and only myObject can change it. myOtherClass does not have permission and it cannot see it.
class myOtherClassTwo
{
private void myfunction()
{
myClass myObject = new myClass();
myObject.myFunction();
}
}
This, thankfully, will work. myFunction was set as public in the myClass class, so it can be seen by anybody outside of the class.
Now the keyword static which you use has a whole different meaning. I advise you not to use it until you've learned about it as you're only adding additional complexity to your problems.
I hope this has cleared things up, though I must urge you to follow some real tutorials as these basics must be thoroughly detailed or you'll be caught out later on.
Since your updateLabel method accesses the label inside the form, correct object-oriented design would dictate that this method should be in the form, too. Then you have no problem accessing newLabel.
Technically speaking: newLabel doesn’t mean anything outside a form object. You could have several copies of your form, which would mean several copies of your newLabel; which of them should it refer to? Of course the computer won’t take a guess there; it’ll expect that you tell it which form you want to use.
The reason you couldn’t access the value variable is because it was private. If you had changed it simply to:
public static int value;
then it would have worked.
From the Form1, call the updateLabel method in the mothods class:
methods updateMethod = new methods();
newLabel.Text = updateMethod.updateLabel();
With this method in the methods class:
public static string updateLabel(){
return "New Value";
}