Home All Groups Group Topic Archive Search About

OOP object instance assignment in sub new()

Author
12 Jun 2006 8:43 PM
syssyx
I have a "CurrentUser" object in session that I want to access from
each page of a vb.net website.  I can successfully access everything if
I include the following at the start of each pageload:

    Dim objCurrentUser As WebsiteClass.CurrentUser =
Session("CurrentUser")
    If objCurrentUser Is Nothing Then objCurrentUser = New
WebsiteClass.CurrentUser

Any page can be linked to directly and not force a login, so without
the second line I get an object instance error.  Right now I only save
the CurrentUser object to session on a successful login:

        If objCurrentUser.IsLoggedIn Then Session.Add("CurrentUser",
objCurrentUser)

Is there a way to include this logic in the class's new method itself,
such as:

    Namespace WebsiteClass
        Public Class CurrentUser
            ...
            Public Sub New()
                If Not HttpContext.Current.Session("CurrentUser") Is Nothing Then
                    Me = HttpContext.Current.Session("CurrentUser")
                End If
            End Sub
        End Class
    End Namespace

so that each codebehind would simply need:

    Dim objCurrentUser As New WebsiteClass.CurrentUser

The trouble I have is I can't seem to assign one instance of a class to
another from within a method of the class, aka "'Me' cannot be the
target of an assignment."  Can this be done, or is this unavoidable
based on the structure of OOP, or is there another way to move the
boolean session operation that will need to occur on each page to the
class itself?  Thanks in Advance!

Brian

Author
13 Jun 2006 6:36 AM
Cor Ligthert [MVP]
Syssex,

Maybe I understand you wrong but why don't you pass the New statement to the
setting.
Be aware that ASPNET is stateless, this means that every object is
automaticly disposed after that the page is sent back to the user.

I think that you want something as (not tested)

If Session.item(user) Is Nothing then
    redirect to home page for validation purpose
    else
    ThisUser = New User(Session.Item(user))
End if

Public class User
    Public Sub New(byval TheUser as String)
        Do the things you want to do
    End sub
End Class
..
I hope this helps,


Cor



<sys***@gmail.com> schreef in bericht
Show quoteHide quote
news:1150145001.990347.25860@j55g2000cwa.googlegroups.com...
>I have a "CurrentUser" object in session that I want to access from
> each page of a vb.net website.  I can successfully access everything if
> I include the following at the start of each pageload:
>
> Dim objCurrentUser As WebsiteClass.CurrentUser =
> Session("CurrentUser")
> If objCurrentUser Is Nothing Then objCurrentUser = New
> WebsiteClass.CurrentUser
>
> Any page can be linked to directly and not force a login, so without
> the second line I get an object instance error.  Right now I only save
> the CurrentUser object to session on a successful login:
>
>        If objCurrentUser.IsLoggedIn Then Session.Add("CurrentUser",
> objCurrentUser)
>
> Is there a way to include this logic in the class's new method itself,
> such as:
>
> Namespace WebsiteClass
> Public Class CurrentUser
> ...
> Public Sub New()
> If Not HttpContext.Current.Session("CurrentUser") Is Nothing Then
> Me = HttpContext.Current.Session("CurrentUser")
> End If
> End Sub
> End Class
> End Namespace
>
> so that each codebehind would simply need:
>
> Dim objCurrentUser As New WebsiteClass.CurrentUser
>
> The trouble I have is I can't seem to assign one instance of a class to
> another from within a method of the class, aka "'Me' cannot be the
> target of an assignment."  Can this be done, or is this unavoidable
> based on the structure of OOP, or is there another way to move the
> boolean session operation that will need to occur on each page to the
> class itself?  Thanks in Advance!
>
> Brian
>
Author
13 Jun 2006 8:23 AM
Göran_Andersson
You can't assign anything to the Me keyword. A constructor (Sub New)
can't return a null reference, it always returns an instance of the class.

Use a factory method to get or create the instance:

Public Shared Sub GetCurrent() As CurrentUser
    Dim objCurrentUser As WebsiteClass.CurrentUser

    objCurrentUser = Session("CurrentUser")
    If objCurrentUser is Nothing Then
       objCurrentUser = New WebsiteClass.CurrentUser
    End If
    Return objCurrentUser
End Sub

If you want to use the constructor, you can't return the actual object
in the session variable, you would have to copy the information from
that object into the newly created instance. That would of course mean
that you would have two separate but identical instances, one referenced
by the session variable and one created in the page.


sys***@gmail.com wrote:
Show quoteHide quote
> I have a "CurrentUser" object in session that I want to access from
> each page of a vb.net website.  I can successfully access everything if
> I include the following at the start of each pageload:
>
>     Dim objCurrentUser As WebsiteClass.CurrentUser =
> Session("CurrentUser")
>     If objCurrentUser Is Nothing Then objCurrentUser = New
> WebsiteClass.CurrentUser
>
> Any page can be linked to directly and not force a login, so without
> the second line I get an object instance error.  Right now I only save
> the CurrentUser object to session on a successful login:
>
>         If objCurrentUser.IsLoggedIn Then Session.Add("CurrentUser",
> objCurrentUser)
>
> Is there a way to include this logic in the class's new method itself,
> such as:
>
>     Namespace WebsiteClass
>         Public Class CurrentUser
>             ...
>             Public Sub New()
>                 If Not HttpContext.Current.Session("CurrentUser") Is Nothing Then
>                     Me = HttpContext.Current.Session("CurrentUser")
>                 End If
>             End Sub
>         End Class
>     End Namespace
>
> so that each codebehind would simply need:
>
>     Dim objCurrentUser As New WebsiteClass.CurrentUser
>
> The trouble I have is I can't seem to assign one instance of a class to
> another from within a method of the class, aka "'Me' cannot be the
> target of an assignment."  Can this be done, or is this unavoidable
> based on the structure of OOP, or is there another way to move the
> boolean session operation that will need to occur on each page to the
> class itself?  Thanks in Advance!
>
> Brian
>
Author
13 Jun 2006 10:04 AM
Cor Ligthert [MVP]
Goran,

Using shared classes in an ASPNET application can be very dangerous.
A shared class is forever used by all active users together in the
application.

Therefore your objCurrenUser, will only be for the first user who starts the
application "Nothing". (As long as there are users (sessions), it will after
that exist)

I know that this is confusing for Winform developers the first time they see
that.

Cor
Author
13 Jun 2006 6:40 PM
Göran_Andersson
You are right about using shared classes in ASP.NET, but I'm not talking
about shared classes at all. The code that I'm showing is a factory
method, just as I mentioned in the post.

If you aren't familiar with the concept, a factory method is used to get
an instance of a class instead of directly using the constructor. A
factory method is usually a shared method, so that you don't have to
create a dummy instance of the class just to be able to call the method.


Cor Ligthert [MVP] wrote:
Show quoteHide quote
> Goran,
>
> Using shared classes in an ASPNET application can be very dangerous.
> A shared class is forever used by all active users together in the
> application.
>
> Therefore your objCurrenUser, will only be for the first user who starts the
> application "Nothing". (As long as there are users (sessions), it will after
> that exist)
>
> I know that this is confusing for Winform developers the first time they see
> that.
>
> Cor
>
>
Author
14 Jun 2006 5:27 AM
Cor Ligthert [MVP]
Goran,

You have a datapart in your sample as an object holding information.
(You even test if it exist and that is the base of my previous message)

Without that it would not be a problem.

Moreover, without that data part I use it too.

(And for real sharing data between users in an aspnet application instead of
a cache)

Cor

Show quoteHide quote
"Göran Andersson" <gu***@guffa.com> schreef in bericht
news:%23dhBajxjGHA.456@TK2MSFTNGP05.phx.gbl...
> You are right about using shared classes in ASP.NET, but I'm not talking
> about shared classes at all. The code that I'm showing is a factory
> method, just as I mentioned in the post.
>
> If you aren't familiar with the concept, a factory method is used to get
> an instance of a class instead of directly using the constructor. A
> factory method is usually a shared method, so that you don't have to
> create a dummy instance of the class just to be able to call the method.
>
>
> Cor Ligthert [MVP] wrote:
>> Goran,
>>
>> Using shared classes in an ASPNET application can be very dangerous.
>> A shared class is forever used by all active users together in the
>> application.
>>
>> Therefore your objCurrenUser, will only be for the first user who starts
>> the application "Nothing". (As long as there are users (sessions), it
>> will after that exist)
>>
>> I know that this is confusing for Winform developers the first time they
>> see that.
>>
>> Cor
>>
Author
14 Jun 2006 5:15 PM
Göran_Andersson
A datapart? What do you mean?

I have search for the term "datapart", and the only remotely related I
found was the usage as "a part of some data".

Are you referring to the local variable that is used in the method?

That is a local variable that is declared for the method. The scope of
the variable is only inside the method, and the lifetime of the variable
is only the duration of the call to the method. When the method returns,
the variable no longer exists.

It's not a shared variable that is stored in the class, if that is what
you are thinking of. Notice the lack of the "shared" keyword in the
declaration of the variable.


Cor Ligthert [MVP] wrote:
Show quoteHide quote
> Goran,
>
> You have a datapart in your sample as an object holding information.
> (You even test if it exist and that is the base of my previous message)
>
> Without that it would not be a problem.
>
> Moreover, without that data part I use it too.
>
> (And for real sharing data between users in an aspnet application instead of
> a cache)
>
> Cor
>
> "Göran Andersson" <gu***@guffa.com> schreef in bericht
> news:%23dhBajxjGHA.456@TK2MSFTNGP05.phx.gbl...
>> You are right about using shared classes in ASP.NET, but I'm not talking
>> about shared classes at all. The code that I'm showing is a factory
>> method, just as I mentioned in the post.
>>
>> If you aren't familiar with the concept, a factory method is used to get
>> an instance of a class instead of directly using the constructor. A
>> factory method is usually a shared method, so that you don't have to
>> create a dummy instance of the class just to be able to call the method.
>>
>>
>> Cor Ligthert [MVP] wrote:
>>> Goran,
>>>
>>> Using shared classes in an ASPNET application can be very dangerous.
>>> A shared class is forever used by all active users together in the
>>> application.
>>>
>>> Therefore your objCurrenUser, will only be for the first user who starts
>>> the application "Nothing". (As long as there are users (sessions), it
>>> will after that exist)
>>>
>>> I know that this is confusing for Winform developers the first time they
>>> see that.
>>>
>>> Cor
>>>
>
Author
14 Jun 2006 5:59 PM
Cor Ligthert [MVP]
Goran,

You are right, I had not good looked at your code the data part of your
method is a local variable.
And accoording to the idea of it, it could work.

However  I have never seen the by you used statemens as

>:Public Shared Sub GetCurrent() As CurrentUser

As well do I not understand how a shared  Function which belong to all users
can use a Session which belong to one user.

I had seen your code as a kind of pseudo but it seems to be reality and in
my idea it will throw a lot of errors and never function this way.

But I keep it by this.

Cor


Show quoteHide quote
"Göran Andersson" <gu***@guffa.com> schreef in bericht
news:Ogem2Y9jGHA.4304@TK2MSFTNGP03.phx.gbl...
>A datapart? What do you mean?
>
> I have search for the term "datapart", and the only remotely related I
> found was the usage as "a part of some data".
>
> Are you referring to the local variable that is used in the method?
>
> That is a local variable that is declared for the method. The scope of the
> variable is only inside the method, and the lifetime of the variable is
> only the duration of the call to the method. When the method returns, the
> variable no longer exists.
>
> It's not a shared variable that is stored in the class, if that is what
> you are thinking of. Notice the lack of the "shared" keyword in the
> declaration of the variable.
>
>
> Cor Ligthert [MVP] wrote:
>> Goran,
>>
>> You have a datapart in your sample as an object holding information.
>> (You even test if it exist and that is the base of my previous message)
>>
>> Without that it would not be a problem.
>>
>> Moreover, without that data part I use it too.
>>
>> (And for real sharing data between users in an aspnet application instead
>> of a cache)
>>
>> Cor
>>
>> "Göran Andersson" <gu***@guffa.com> schreef in bericht
>> news:%23dhBajxjGHA.456@TK2MSFTNGP05.phx.gbl...
>>> You are right about using shared classes in ASP.NET, but I'm not talking
>>> about shared classes at all. The code that I'm showing is a factory
>>> method, just as I mentioned in the post.
>>>
>>> If you aren't familiar with the concept, a factory method is used to get
>>> an instance of a class instead of directly using the constructor. A
>>> factory method is usually a shared method, so that you don't have to
>>> create a dummy instance of the class just to be able to call the method.
>>>
>>>
>>> Cor Ligthert [MVP] wrote:
>>>> Goran,
>>>>
>>>> Using shared classes in an ASPNET application can be very dangerous.
>>>> A shared class is forever used by all active users together in the
>>>> application.
>>>>
>>>> Therefore your objCurrenUser, will only be for the first user who
>>>> starts the application "Nothing". (As long as there are users
>>>> (sessions), it will after that exist)
>>>>
>>>> I know that this is confusing for Winform developers the first time
>>>> they see that.
>>>>
>>>> Cor
>>>>
>>
Author
14 Jun 2006 6:52 PM
syssyx
A huge thank you again to Cor and Göran!  I greatly appreciate the
knowledge you shared!

Cor, I've used a lot of functions that reference the session variable
using httpcontext.current.session.  In the past I've had to create a
dummy instance of the "function library" class to get to them like
Göran described above.  But I plan to try the public shared
subroutines mentioned, so that may have just changed! :)

Brian
Author
14 Jun 2006 7:26 PM
Göran_Andersson
Cor Ligthert [MVP] wrote:
> Goran,
>
> You are right, I had not good looked at your code the data part of your
> method is a local variable.
> And accoording to the idea of it, it could work.
>
> However  I have never seen the by you used statemens as
>
>> :Public Shared Sub GetCurrent() As CurrentUser
>
> As well do I not understand how a shared  Function which belong to all users
> can use a Session which belong to one user.

That is not a problem. The call to the method is still specific for the
user.

Actually, the shared keyword for methods doesn't really have anything to
do with sharing the method between users. As a method only is loaded
once into memory, the code for a method is always shared by all users,
regardless if the method is declared as shared or not.

The shared keyword for a method only means that the method is called
without the use of an instance of the class.

The "shared" keyword in VB is somewhat confusing when used this way.
Consider that other languages uses the "static" keyword instead, which
makes more sense in this context.

> I had seen your code as a kind of pseudo but it seems to be reality and in
> my idea it will throw a lot of errors and never function this way.

No, there is nothing wrong with the code. I assure you that it works
just fine.

Show quoteHide quote
> But I keep it by this.
>
> Cor
>
>
> "Göran Andersson" <gu***@guffa.com> schreef in bericht
> news:Ogem2Y9jGHA.4304@TK2MSFTNGP03.phx.gbl...
>> A datapart? What do you mean?
>>
>> I have search for the term "datapart", and the only remotely related I
>> found was the usage as "a part of some data".
>>
>> Are you referring to the local variable that is used in the method?
>>
>> That is a local variable that is declared for the method. The scope of the
>> variable is only inside the method, and the lifetime of the variable is
>> only the duration of the call to the method. When the method returns, the
>> variable no longer exists.
>>
>> It's not a shared variable that is stored in the class, if that is what
>> you are thinking of. Notice the lack of the "shared" keyword in the
>> declaration of the variable.
>>
>>
>> Cor Ligthert [MVP] wrote:
>>> Goran,
>>>
>>> You have a datapart in your sample as an object holding information.
>>> (You even test if it exist and that is the base of my previous message)
>>>
>>> Without that it would not be a problem.
>>>
>>> Moreover, without that data part I use it too.
>>>
>>> (And for real sharing data between users in an aspnet application instead
>>> of a cache)
>>>
>>> Cor
>>>
>>> "Göran Andersson" <gu***@guffa.com> schreef in bericht
>>> news:%23dhBajxjGHA.456@TK2MSFTNGP05.phx.gbl...
>>>> You are right about using shared classes in ASP.NET, but I'm not talking
>>>> about shared classes at all. The code that I'm showing is a factory
>>>> method, just as I mentioned in the post.
>>>>
>>>> If you aren't familiar with the concept, a factory method is used to get
>>>> an instance of a class instead of directly using the constructor. A
>>>> factory method is usually a shared method, so that you don't have to
>>>> create a dummy instance of the class just to be able to call the method.
>>>>
>>>>
>>>> Cor Ligthert [MVP] wrote:
>>>>> Goran,
>>>>>
>>>>> Using shared classes in an ASPNET application can be very dangerous.
>>>>> A shared class is forever used by all active users together in the
>>>>> application.
>>>>>
>>>>> Therefore your objCurrenUser, will only be for the first user who
>>>>> starts the application "Nothing". (As long as there are users
>>>>> (sessions), it will after that exist)
>>>>>
>>>>> I know that this is confusing for Winform developers the first time
>>>>> they see that.
>>>>>
>>>>> Cor
>>>>>
>
Author
13 Jun 2006 7:26 PM
syssyx
First, thanks Cor and Göran for the help!

The function looks to be just what I wanted as far as putting the test
in one location and not in each script, although it sounds like what
I'm looking for is not the ideal. :)  Am I correct that it would only
duplicate the attributes and utilize one copy of the methods?  The
CurrentUser object also "has-a" object that accesses CurrentUser
properties, similar to the code in
http://groups.google.com/group/microsoft.public.dotnet.languages.vb/browse_thread/thread/7c8fa285c54b54ca

        Namespace WebsiteClass
                Public Class CurrentUser
            Public AnotherObject As AnotherClass.AnotherObject
            ...
                        Public Sub New()
                AnotherObject = New AnotherClass.AnotherObject(me)
                        End Sub
                End Class
        End Namespace
        Namespace AnotherClass
                Public Class AnotherObject
            Private _CurrentUser As WebsiteClass.CurrentUser
            ...
                        Public Sub New(ByRef CU As
WebsiteClass.CurrentUser)
                _CurrentUser = CU
                        End Sub
            Public Sub AnotherFunction()
                somehowuse(_CurrentUser.SomeProperty)
            End Sub
                End Class
        End Namespace

Will this passing of the CurrentUser to AnotherClass duplicate the
object methods?  I thought ByRef wouldn't and ByVal would, but it looks
like they really mean IN and IN/OUT, so it sounds like I should use
ByVal whenever possible, rather than the other way around.  And would
combining this with the function Göran mentioned result in 4
instances?  I sound nit-picky but the CurrentUser object is growing
quickly to incorporate a lot of business logic and I'm still trying to
get my arms around all this!

Brian
Author
13 Jun 2006 11:00 PM
Göran_Andersson
sys***@gmail.com wrote:
> First, thanks Cor and Göran for the help!
>
> The function looks to be just what I wanted as far as putting the test
> in one location and not in each script, although it sounds like what
> I'm looking for is not the ideal. :)  Am I correct that it would only
> duplicate the attributes and utilize one copy of the methods?

There is always only one copy of the methods. An instance of an object
doesn't contain the methods, it only has the ability to use the methods.
The compiler keeps track of what objects can use which methods.

An object instance only contains it's (non-shared) member variables.

Show quoteHide quote
>  The
> CurrentUser object also "has-a" object that accesses CurrentUser
> properties, similar to the code in
> http://groups.google.com/group/microsoft.public.dotnet.languages.vb/browse_thread/thread/7c8fa285c54b54ca
>
>         Namespace WebsiteClass
>                 Public Class CurrentUser
>             Public AnotherObject As AnotherClass.AnotherObject
>             ...
>                         Public Sub New()
>                 AnotherObject = New AnotherClass.AnotherObject(me)
>                         End Sub
>                 End Class
>         End Namespace
>         Namespace AnotherClass
>                 Public Class AnotherObject
>             Private _CurrentUser As WebsiteClass.CurrentUser
>             ...
>                         Public Sub New(ByRef CU As
> WebsiteClass.CurrentUser)
>                 _CurrentUser = CU
>                         End Sub
>             Public Sub AnotherFunction()
>                 somehowuse(_CurrentUser.SomeProperty)
>             End Sub
>                 End Class
>         End Namespace
>
> Will this passing of the CurrentUser to AnotherClass duplicate the
> object methods?

No, nothing is duplicated. The only thing that is sent to the
constructor of the AnotherClass is a reference to the CurrentUser object.

As you have declared the parameter as ByRef it actually only accepts a
reference variable. As Me is not a variable, the reference is first
copied to a temporary variable, and the reference to the temporary
variable is sent to the constructor. The compiler creates code that does
the same thing as:

Dim temp as CurrentUser = Me
AnotherObject = New AnotherClass.AnotherObject(temp)

As the reference is sent using ByRef, you have the ability to change the
variable used in the method call from within the method. In this case
that would mean that you would change the temporary variable that was
created for the call, but as that variable isn't used for anything once
the method returns, the change wouldn't affect anything.

> I thought ByRef wouldn't and ByVal would, but it looks
> like they really mean IN and IN/OUT, so it sounds like I should use
> ByVal whenever possible, rather than the other way around.

Yes, stick to ByVal. All parameters are passed by value unless you
specify ByRef, so you can omit the ByVal keyword (unless you want to be
extra obvious somewhere).

When you are passing an object by value, that doesn't mean that the
object is copied. It means that the value of the reference to the object
is copied. Objects are never copied unless you specifically ask for it.

> And would
> combining this with the function Göran mentioned result in 4
> instances?

No.

Show quoteHide quote
> I sound nit-picky but the CurrentUser object is growing
> quickly to incorporate a lot of business logic and I'm still trying to
> get my arms around all this!
>
> Brian
>