c# - How to get reference to object A inside A's class? - c#

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.

Related

Can't instantiate public instance of class from form code

I'm working on a windows forms application in c# and I can't figure out why I can't instantiate a class object from my form code. I have several classes, and from within all of those I can instantiate instances of the other classes publicly or just within methods with no problem.
However, when I try to instantiate one of those classes from my main form, it doesn't work.
It doesn't even recognize that I've just created an instance of the class.
The real kicker is that I can successfully instantiate a class from inside a method in my frmMain class:
private void Form_Load()
{
long deltaTime; int i; int page;
if (releaseMode)
{
modCanCable can = new modCanCable();
can.WaitWhileBusy();
}
All of the classes and form classes are under the same namespace too. Please let me know if you need to me to include any more information to help me find an answer!
You can only declare the global variable at the class level. Making use of that global variable must be done inside a property, method, or function.
For a global enumerator, declare it like you would any other variable
private EnumeratorClass VariableName;
Example (following naming conventions)
private MyEnum _myVariableName;
In C# all code has to be inside of a method. The line modCanCable can = new modCanCable(); declares a private field and uses a field initializer to initialize it to a new modCanCable instance. Any other refrence to the can field must be inside of a method body.
It must be done within a method or constructor. You cannot put it just in the class.
public partial class frmMain : Form
{
modCanCable cab = new modCanCable();
public frmMain()
{
cab.property = "asd";
}
}

public vs public static Methods

Having read the access modifiers in C# progamming tutorial, I come to conclusion that defining a method public is enough for it to be "seen" from another Form of the same namespace.
However, in practise whenever I tried to implement this, I also had to define the method as static in order for it to be referenced from other Forms of the same namespace.
Am I loosing something?
I am doing somethning wrong?
For a public static method, you don't need a reference to an object. The method is static and can be accessed on class level.
If you can't access a public method, then you need a reference to the object, then you can.
public class AClass
{
public void DoSomething() {}
public static void DoSomethingElse() {}
}
You can use them as follows:
AClass.DoSomethingElse(); // no object reference required
AClass.DoSomething(); // will give compiler error, since you have no object reference.
var anObject = new AClass();
anObject.DoSomething(); // will work fine.
anObject.DoSomethingElse(); // compile error (thx hvd).
public static method do not need object instance, they can be used without creating any instance of the class
ClassName.MyStaticPublicMethodName()
where as public (non-static) method require an Instance of the Class, public (non-static) method in general helps you to work with the data member (field) of the object.
To use a non-static public method you need to create instance of the class
ClassName obj = new ClassName();
obj.MyPublicMethod();

Losing reference to an object When a Subclass tries to use that object

this is weird to me, it's got to be something obvious but when using Selenium who knows...I haven't used Selenium until now.
But here is just basic code I think and I think it's just a syntax/OOP issue but not sure what.
Lets say I have a base class that has a driver property and a method where I'm getting the problem happening later on:
public Abstract BaseTest
{
protected IWebTestDriver TestDriver {get; set;}
...more code
protected void WaitForGridToRender(double seconds)
{
TestDriver.Wait(TimeSpan.FromSeconds(seconds));
}
}
I then have a test class called MyTests.cs that inherits BaseTest and in it an NUnit test:
[TestFixture]
public class MyTests : BaseTest
{
[Test]
public void SomeTab_WhenClicked_ShowsSomething()
{
SomeLandingPage someLandingPage = new SomeLandingPage(TestDriver);
mainLandingPage.NavigateToTheMainPage();
... rest of code
}
.. other test methods
}
And I have a 3rd class that serves as a "PageObject" that allows me to just reuse certain elements on the page, get at some things (more DRY) than have these same common methods repeated throughout my test methods:
public class MyPageObject : BaseWebTest
{
public void NavigateToTheMainPage()
{
// wait for the user to log in
WaitForGridToRender(5);
}
}
Now here's where my problem is and how things are being called:
1) The Base class is first initialized...meaning that TestDriver's instance is created and set to the TestDriver property so we can use it in subclasses
2) Eventually some code in another class that I did not mention here is called from the Base Class which just sends some calls to opens up FireFox, does some stuff...nothing special here
3) Eventually control goes to my test method and eventually hits the SomeTab_WhenClicked_ShowsSomething() method which then calls the MyPageObject.NavigateToTheMainPage() method.
The NavigateToTheMainPage() tries to call the BaseTest method called WaitForGridToRender and control eventually gets there.
Now the problem is, up till when WaitForGridToRender is called from within MyPageObject, that BaseTest.TestDriver instance has been there and accessible to both my test class and my PageObject class.
But when I finally debug and get to this line in WaitForGridToRender:
TestDriver.Wait(seconds);
Now for some reason, I get a null ref on TestDriver...the reference instance for that property is gone!
No idea why which is why I'm posting this cause I'm stuck as to why this might happen.
1) The Base class is first initialized...meaning that TestDriver's instance is created and set to the TestDriver property so we can use it in subclasses
This code
protected IWebTestDriver TestDriver {get; set;}
declares a protected property of type IWebTestDriver named TestDriver.
Unless you're setting TestDriver to something in a constructor or method not shown here, the backing variable for TestDriver contains a null reference.

Using certain variables in different classes (C#)

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";
}

How does one access a control from a static method?

I have an application in C# .NET which has a MainForm and a few classes.
One of these classes receives incoming data messages from a network. I need to get these message's text appended into a multi-line textbox on the MainForm.
I can send the message to a method in the MainForm by making the method static, but then the static method cannot access the MainForm's controls.
TheIncomingDataClass.cs
namespace TheApplicationName
{
class TheIncomingDataClass
{
public void IncomingMessage(IncomingMessageType message)
{
TheApplicationName.MainForm.ReceiveMSG(message);
}
MainForm.cs
public static void ReceiveMSG(string message)
{
txtDisplayMessages.AppendText(message); //This line causes compile error
}
The compile error:
An object reference is required for the nonstatic field, method, or
property 'TheApplicationName.MainForm.txtDisplayMessages'
A static method doesn't have access to members like txtDisplayMessages because it is not a part of that instance. I suggest you do some reading on the concepts of static methods and whatnot, because that is a fairly language agnostic concept. That method would best be served by removing the static modifier, because it doesn't need to be static - it appears that it would need to be called by that particular instance of that object.
To continue the way you've been doing it, your "TheIncomingDataClass" should have a reference to the MainForm object with which it should interface. When you create an instance of this class (presumably from an instance method of MainForm), you will need to pass in a reference to this MainForm object.
class TheIncomingDataClass{
MainForm form;
public TheIncomingDataClass(MainForm form){
this.form = form;
}
}
class MainForm : Form{
MainForm(){
new TheIncomingDataClass(this);
}
}
However, as suggested by Bugs, you probably would be better off making this an event on TheIncomingDataClass and subscribing to it from MainForm.
class IncomingMessageEventArgs : EventArgs{
IncomingMessageType message;
public IncomingMessageType Message{get{return message;}}
public IncomingMessageEventArgs(IncomingMessageType message){
this.message = message;
}
}
class TheIncomingDataClass{
public event EventHandler<IncomingMessageEventArgs> MessageReceived;
protected virtual void OnMessageReceived(IncomingMessageEventArgs e){
if(MessageReceived != null)
MessageReceived(this, e);
}
public void IncomingMessage(IncomingMessageType message){
OnMessageReceived(new IncomingMessageEventArgs(message));
}
}
class MainForm : Form{
MainForm(){
new TheIncomingDataClass().MessageReceived +=
(s, e)=>txtDisplayMessages.AppendText(e.Message.ToString());
}
}
Its possible to pass in a reference to the current form like this:
public static void ReceiveMSG(string message, MainForm mainform)
{
mainform.txtDisplayMessages.AppendText(message);
}
Although as suggested an event is probably a better way of doing it.
raise an event from class which the form can subscribe to.
Just remove the static modifier, you don't need it for your purposes. Read about statics here.
You can solve this problem by removing the static keyword.
When you see "static", think: without an instance of this type.
When you call a non-static method, you must explicitly use some instance. The method can access that instance using the "this" keyword.
When you call a static method, there is no instance - you have abandoned the boundaries of OO and are now in a structural or functional programming context. If you want an instance of something, you need to bring it in as a parameter.
I think you might be taking the wrong approach on this. It sounds like you are trying to push messages to a client from an external process. There are ways to do this, but it will get complicated. My suggestion would be to have the client poll whatever process has the data periodically - maybe every 10 seconds depending on your needs. This is going to be a heck of a lot easier than pushing from server to client.
Ok here goes.
Static methods can access only static members. Your ReceiveMSG method is static. txtDisplayMessages is not and hence you cant access it.
Why does your method need to be static? Needless to say, if you remove the static keyword that will fix your problem.
Just make ReceiveMSG part of a class, create an instance of the class and then call the method on the instance.
I think you should post the kind the solution you are expecting.
Seeing as you are new to C# I will keep this as simple as possible. You should have a Program.cs file that has a single method Main (this would have been generated by Visual Studio). You will need to make it look like the following:
class Program
{
public static readonly MainForm MainForm;
static void Main()
{
Application.EnableVisualStyles();
MainForm = new MainForm(); // These two lines
Application.Run(MainForm); // are the important ones.
}
}
Now in your incoming message you will have a way to access that form.
public void IncomingMessage(IncomingMessageType message)
{
Program.MainForm.RecieveMSG(message);
}
That method in the form would then be a instance (not static) method. E.g.
public void RecieveMSG(IncomingMessageType message) // NB: No static
{
txtDisplayMessages.Text = message.Text; // Or whatever.
}
There are better ways to do it - but as a beginner I think this would be the best approach.
The difference between static and instance (instance is when you don't say static) is huge. To get to an instance method, field or property (which are collectively called members in C#) you need to have the containing instance. So:
Person p = new Person(); // You now have an instance.
p.Name = "Fred"; // You are using an instance property.
Static are the opposite, they are the same anywhere in your application (more technically within the same AppDomain - but if you are a beginner you won't need to worry about that for a while). You don't need an instance to get to them (props to codewidgets "Static methods can access only static members"). For example:
// Where Planet is a class and People is a static property.
// Somewhat confusingly the Add method is an instance - best left for the student :).
Planet.People.Add(new Person("Fred"));
Hopefully that gives you a good indication of what static and instance is and where to use them. The most important thing though is to try and avoid static members as best as you can - they can cause maintenance nightmares.
Microsoft has a whole write-up on the important concepts in regard to this.
private void FormMain_Load(object sender, EventArgs e)
{
TheIncomingDataClass.SetupControl(textBox1);
}
public class TheIncomingDataClass
{
public static TextBox textbox = new TextBox();
public static void SetupControl(TextBox txt)
{
textbox = txt;
}
public void IncomingMessage(string message)
{
textbox.Text = message;
}
}

Categories