circular reference and events

M

mp

back to the view/presenter/business project
...just tell me when you all are sick of my stupid beginner
box-of-rocks-for-a-brain questions

trying to experiment with the "push/pull" topic Peter brought up
i had this exchange with Peter recently on another thread.,..
me:
1 my business object Portfolio.cs gets a string from somewhere that it
wants
to display
2 it raises an event GotStringToDisplay(string str) (or whatever better
name) when it has it...
3 the presenter InvestmentPresenter.cs (another badly named object i know)
subscribes to that event
and raises it's own event GotStringToDisplay(string str)
4 the view(form) InvestmentView.cs subscribes to that event and fills it's
datagrid (or whatever other control) with the string???

am i even close???

peter:
That all seems fine.

so i went to try and implement
what i forgot to mention is what happens before #1 above
A. User clicks button
B. Button raises event
C.Presenter catches event and raises it's own event so Portfolio.cs can
catch that event - causing it to go get data
that's what triggers #1 above.

so for presenter to raise an event that business object catches, business
obj has to have reference to presenter

so far how i know to raise/catch events is to have a refernce to the
'raising' object in the 'catching' object
for example for my view to talk to my presenter...in my presenter i have a
reference to my view
private IInvestmentsView mView;

in presenter subscribe to view event
this.mView.LoadInvestments += new
EventHandler<EventArgs>(mView_LoadInvestments);
so i thought for the business object to subscribe to a presenter event (go
get property) the business object needs a reference to the presenter

and for the presenter to subscribe to an event from the business object
(property_changed) the presenter needs a reference to the business object

when i try to do that i get a circular reference error

is there another way to subscribe to events that don't require a reference
to the object?

can you not have two-way events?

object1 raises event "call"

object2 catches event "call"

object2 raises event"response"

object1 catches event "response"

???

thanks

mark
 
M

mp

Peter Duniho said:
[...]
so far how i know to raise/catch events is to have a refernce to the
'raising' object in the 'catching' object
[]
Finally, I should emphasize that my suggestion about directly subscribing
a view to the model is mainly about expediency. Strictly speaking, the
presenter/controller would really be mediating always. Doing it the
"official" way helps make it easier to avoid these kinds of potentially
confusing inter-dependencies.

Pete

thanks for all that
i'll have to chew on it for a while
thanks
mark
 
M

mp

Peter Duniho said:
[...]
so far how i know to raise/catch events is to have a refernce to the
'raising' object in the 'catching' object

For an object to signal an event to a subscriber, it does need a reference
to the object that has subscribed to the event.

I thought it was the other way around. I thought that an event being raised
was like broadcasting...
the 'raiser of the event' doesn't know or care who is 'listening' - it just
raises an event.
The listener is the one who knows about the 'raiser' and
subscribes to the events it's interested in....
no?

[...]

Finally, for that to
work you are trying to add a reference in assembly A to assembly B, and a
reference in assembly B to assembly A.

If that's not what you mean, then your description doesn't make sense.

yes that's what i meant.

to explain my current misconception:

Presenter project has a reference to view and subscribes to views event(go
get some data)
Presenter raises event that business project subscribes to (go get some
data)
that means business project has a reference to Presenter project in order to
subscribe to it's events
....so far this works...
based on your idea about "pull vs push"
I thought i wanted the business project to then raise an event (data_ready?)
once it had the data
and to pass that string back to the presenter which would pass it back to
the view
and the view would then display the data in some way
so i thought the presenter had to have a reference to the business object to
subscribe to it's event (data_ready)
the presenter would then either push that data to the view,
or the presenter would raise it's own data_ready event
and the view would subscribe to that???

that's when i got the circular reference, trying to make the presenter see
the business object
after the business object already knew about the presenter
In fact, the _normal_ way to subscribe to events does not require the type
that publishes the event to know the type of any subscriber to the event.
The only type in common that each class needs to know is the delegate type
for the event itself. That's one of the great things about delegate
types; they (like interfaces) provide an abstracted type that describes a
specific method signature. Any type can implement that method signature
and provide a reference to a delegate instance of that signature. And any
type can invoke a delegate of that type, without knowing or caring the
type of the object that is the target for the delegate instance.
[..]

i'm going to look for some tutorials on events
i'm so confused

http://www.codeproject.com/KB/cs/event_fundamentals.aspx
looks like a thorough review....maybe that will help

thanks
mark
 
K

kndg

Peter Duniho said:
[...]
so far how i know to raise/catch events is to have a refernce to the
'raising' object in the 'catching' object

For an object to signal an event to a subscriber, it does need a reference
to the object that has subscribed to the event.

I thought it was the other way around. I thought that an event being raised
was like broadcasting...
the 'raiser of the event' doesn't know or care who is 'listening' - it just
raises an event.
The listener is the one who knows about the 'raiser' and
subscribes to the events it's interested in....
no?

Here is the classic observer pattern. Hopefully it can shed some light
to you...

using System;
using System.Collections.Generic;

namespace MyNamespace
{
public interface IObserver
{
void DoSomething();
}

// the publisher
public class Subject
{
private readonly List<IObserver> observers = new List<IObserver>();

public void Register(IObserver observer)
{
if (!observers.Contains(observer))
{
observers.Add(observer);
}
}

public void UnRegister(IObserver observer)
{
if (observers.Contains(observer))
{
observers.Remove(observer);
}
}

public void Notify()
{
foreach (IObserver observer in observers)
{
observer.DoSomething();
}
}
}

// the subscriber
public class Observer : IObserver
{
public string Message { get; private set; }

public Observer(string message)
{
Message = message;
}

public void DoSomething()
{
Console.WriteLine(Message);
}
}

// sample usage
public class MyClass
{
public static void Main(string[] args)
{
var publisher = new Subject();
var subscriber1 = new Observer("Hi");
var subscriber2 = new Observer("Hello");

publisher.Register(subscriber1);
publisher.Register(subscriber2);

publisher.Notify();
}
}
}
 
K

kndg

Here is the classic observer pattern. Hopefully it can shed some light
to you... [...]

I agree that the code you posted is the classic observer pattern…in a
language that _doesn't_ have events (like Java). I'm not sure what the
relevant is here, except perhaps to illustrate how much nicer events are
than doing things the Java way. Was that your intent?

My intention is to give the OP some idea how the event works. Some
people (at least from my experience), know how to write the event but
somehow still struggling on how and when to use it.
 
M

mp

Peter Duniho said:
On 1/12/11 8:57 PM, kndg wrote:
Here is the classic observer pattern. Hopefully it can shed some light
to you... [...]
[]

Ah, okay. It might have been useful for you to be more explicit about
that in your post. :)

Thanks again kndg and Peter.
More great info for me to digest.

the older i get the more times
i have to re-read something
before it really sinks in...
I know the info is there thanks to your generous help
Now I need to get it to absorb.
many many Thanks
mark
 
M

mp

Peter Duniho said:
For the source of the event to invoke a method on the destination
object, it must have a reference to that object. It cannot do it any
other way.

Delegate types encapsulate this reference. Thus, the source of the event
does not need to directly deal with the question. But there is always an
implicit reference in the delegate instance, and the delegate instance is
stored in the _source_ when the event is subscribed.

so that's something hapening behind the scenes, not something i write into
my code?
[...]
Presenter project has a reference to view and subscribes to views
event(go
get some data)

Please be precise. A _project_ does not have a reference to any
particular type. Projects reference assemblies, source code can reference
other objects.

Yes, i was speaking out of the side of my head, sorry.<g>
I have layer upon layer of misunderstandings floating around inside my
brain. :)
what i was thinking was....
Presentation project has a reference to View project(in references in
solution explorer)
...so that ...
presenter_object can get a reference to View_object.(in code)

however,...
going back and looking again i was surprised to see that Presentation
project does not have a reference to view project
presenter defines an interface that the view implemented

public class InvestmentPresenter
{
private IInvestmentsView mView;
...
then when the view creates the presenter, the presenter_object gets it's
reference to the view_object
public InvestmentPresenter(IInvestmentsView view)
{
this.mView = view;
this.Initialize();
}

private void Initialize()
{
this.mView.LoadInvestments += new
EventHandler<EventArgs>(mView_LoadInvestments);

....i had forgotten that part....

and maybe it's more correct to say presentation project has a reference to
view assembly?
I called it project because in the ide i go Add Reference | Projects Tab |
select project to reference.
Is Assembly somewhat synonymous with Project? or is it synonymous with the
..dll file that is created
when the project builds?
Can we assume here that you really mean that the presenter _object_ keeps
a reference to the view _object_?
yes

If so, then sure. the presenter would typically subscribe to events that
are raised when specific user actions are performed in the view.


Let's assume by "business project" you really mean "model object".

yes, better term
It may. Or it may call a method on the model _object_ that is known to
the presenter (either because of an implemented interface, or because it's
hard-coded to the model type).

ah! that's what i wasn't doing...(cause i'm just following/adapting an
existing example from the net)
the presenter creates an interface for the view to implement
but i can also have the presenter create an interface for the model to
implement!?!

[]
For example:

interface IPresenter <<< is this defined in the presenter.cs?
[]
interface IModel <<< is this defined in the presenter.cs?

[]
thanks for that example, i'll play with that for a while
As I mentioned before, the main thing is to make sure you've got a good
mental model of the data flow, and understand what types are responsible
for what.

[]

at this point my data flow is simple, it's groking the structure of writing
the events
thats' been giving me headaches....
:)
it's slowly getting more clear...thanks to your help (and everyones')
Personally, at first glance it seems a bit _too_ thorough.

[]

sometimes i get too much info input and it actually makes it harder for me
to get the simple background concepts...
eventually this will all sink in
and i'll wonder why i thought it was so hard
:)


If you find the
article a good read, there's plenty of helpful advice in it.

Pete

thanks again
mark
 
M

mp

Peter Duniho said:
Peter Duniho said:
On 1/12/11 1:48 PM, mp wrote:
[...]
[...]


There's a lot of heavy-lifting going on behind the scenes for you when you
use events and delegates. Aren't you happy you don't have to write all
that code yourself? :)

I feel better already
:)


[...]

Yes, definitely.

Pete

I tried that and ran into a problem
The view has a refernce to the Presenter assembly/project
The presenter defines an interface for the view
The view can see and implemment that int. because it has a "using Presenter"
but when i tried to write an interface for the Model it doesn't work
because the Presenter has a ref to the Model assy/proj but not the other way
around
so when I wrote the interface in the presenter
and tried to implement it in the Model,
the model can't "see" the interface

---again---the structure i have is just copied from the tutorial i'm trying
to follow
so maybe it doesn't have to be this way, but it was supposed to be a
canonical?
demonstration of the MVP pattern

should the Model have a reference to the Presenter instead of the other way
around?
or should i be defining the interface in the model, and then have the
Presenter work
against that somehow???

I know I should just get some c# books and hole up for a year or two,
but its much more fun enjoying the company and wisdom of you folks here on
the ng
:)
mark
 
M

mp

Peter Duniho said:
[...]
The view has a refernce to the Presenter assembly/project
The presenter defines an interface for the view
The view can see and implemment that int. because it has a "using
Presenter"
but when i tried to write an interface for the Model it doesn't work
because the Presenter has a ref to the Model assy/proj but not the other
way
around
so when I wrote the interface in the presenter
and tried to implement it in the Model,
the model can't "see" the interface

In this kind of scenario, often the right thing to do is have yet another
assembly, in which your interfaces are defined. It won't reference any
other assembly, but rather it will just define the interface types common
to all three assemblies.

Another way to do it would be to define the interfaces in the model
assembly.

both for the view and the model?
in other words, move the view interface from the presenter into the model?
then instead of(or in addition to?) the view referencing the presenter it
refs the model?

After all, the presenter and view exist only to serve the
model. It's much more likely you'd change the view or the controller than
the model, since after all.if you change the model, you've got a
completely different program. :)

I wondered about that too. I was originally surprised that the presenter
defined
the interface for the view. I previously thought the object/project/assy
itself
would have been responsible for defining it's own interface. probably just
confused again.
The bottom line is just to keep in mind that there's going to be a
definite hierarchy of reference relationships between the assemblies (no
circular references.an acyclic graph, if you will), and that shared types
need to be declared at the lower levels of that hierarchy, so that all the
types higher up have access to them.

Pete

so in this context is Model the lowest level or highest?
 
M

mp

Peter Duniho said:
[...]
Another way to do it would be to define the interfaces in the model
assembly.

both for the view and the model?

And even the presenter, yes.
in other words, move the view interface from the presenter into the
model?
then instead of(or in addition to?) the view referencing the presenter it
refs the model?

Again, ideally none of the components reference the exact _implementation_
types. So, yes.the view, presenter, and model interfaces could all be in
the model project.

what i mean is if i put the interface for the view(IInvestmentsView) in the
model,
in order for the view to implement(or derive from?) the interface,
namespace Investments.ViewLayer
{
public partial class InvestmentsView : Form, IInvestmentsView <<<view
has to see this definition (see the namespace in which it's written)
{

the view project has to have a reference to the model project
other wise i get an error saying xxx does not exist in namespace yyy
Of course, the presenter needs to know the implementation types to get
things set up. That is, instantiate the relevant object types. But once
the objects exist, all interaction _can_ occur through interfaces,
assuming those interfaces are defined well enough.

Finally note that all of this assumes the different components are split
into different projects. In reality, it's not uncommon to find all three
in the same project. In that case, there is no problem with type
references at all, as all types are equally available to all other types.

or can i just change all the namespaces to Investments and leave off the
..modifiers?

[]

thanks
mark
 
M

mp

Peter Duniho said:
Yes, it does. But what's wrong with that?

oh i guess i snipped too much, the sentence that was a response to was:
**************************
in other words, move the view interface from the presenter into the model?
then instead of(or in addition to?) the view referencing the presenter it
refs the model?

Again, ideally none of the components reference the exact
_implementation_ types. So, yes.the view, presenter, and model
interfaces could all be in the model project.
**************************


[...]
Personally, I would just keep everything in the same assembly. It's bad
enough you're trying to come to grips with the MVC/MVP patterns, before
you really have a good handle on C# and OOP generally. Why give yourself
even more headaches trying to deal with assembly referencing issues on top
of all that?

sounds like heaven at this point!!! :)))))))
I've just been trying to follow this tutorial i was guided to
I had no idea how hard it was going to be

[...]
Only putting things in the same assembly does.

Pete

thanks
mark
 
M

mp

Peter Duniho said:
On 1/14/11 4:21 PM, mp wrote:

Another option is to use a factory pattern, in which the view project
references the presenter project, where the view interface is declared.
But since the presenter can't reference the view project, it needs a way
to be able to create view instances without that reference.

It can do so by defining a factory interface in addition to the view
interface, with the view class registering its factory interface
implementation somehow with the presenter class. Then the presenter uses
the factory to create instances of the view.

that sounds like the presenter then becomes the startup object???
at this point the view is and program.cs calls the Form
[STAThread]
static void Main()
{
Application.Run(new InvestmentsView());

....maybe that was wrong from the get go???

[]
Personally, I would just keep everything in the same assembly. It's bad
enough you're trying to come to grips with the MVC/MVP patterns, before
you really have a good handle on C# and OOP generally. Why give yourself
even more headaches trying to deal with assembly referencing issues on top
of all that?

I want to try that. I guess the easiest way to convert the existing multi
folder/project setup
is to copy the main folder and rename "Investments2"
move all the cs files into the main folder out of their respective
subfolders
get rid of everything else
then start a new project from scratch, adding all the cs files and then
rename all the
namespaces to Investments....
there's no advantage to keeping the .Presenter .View .Model namespaces in
the
various cs files??? or should i keep that distinction but just have them
all live in the
one assembly?



[]
Only putting things in the same assembly does.

Pete

thanks
mark
 
M

mp

Peter Duniho said:

I'm trying the following example...
For example:

interface IPresenter
{
event EventHandler DataNeeded;
}

interface IModel
{
void Subscribe(IPresenter presenter);
}

class Presenter : IPresenter
{
public event EventHandler DataNeeded;

IModel model;

void Initialize()
{
model = new Model();

model.Subscribe(this);
}
void RequestData()
{
if (DataNeeded != null)
{
DataNeeded(this, EventArgs.Empty);
}
}
}

class Model : IModel
{
void Subscribe(IPresenter presenter)
{
presenter.DataNeeded += presenter_DataNeeded;
}
void presenter_DataNeeded(object sender, EventArgs e)
{
IPresenter presenter = (IPresenter)sender;
// do whatever
}
}
[...]

Pete

looks like i have to change
void Subscribe(IPresenter presenter)
to
public void Subscribe(IPresenter presenter)

is that right?
which got me to wondering
why doesn't
class Model : IModel
have to be
public class Model : IModel

presenter could still see Model even though it wasn't defined public
i thought default in c# was private for anything not defined public or
other?

same with interfaces
they don't seem to need public modifier
still other classes can see them?!?

thanks
mark
 
M

mp

Peter Duniho said:
\
In this kind of scenario, often the right thing to do is have yet another
assembly, in which your interfaces are defined. It won't reference any
other assembly, but rather it will just define the interface types common
to all three assemblies.
[]
Pete

now that i've moved everything into the same project/assy
does the above still apply...if i replace
"yet another assembly,"
with
"yet another class"
???
ie make a class that holds all the interfaces?

in one of your other examples
interface IPresenter {
event EventHandler DataNeeded;
}

interface IModel
{
void Subscribe(IPresenter presenter);
}

was the intention:
IModel defined in the presenter?
and IPresenter is defined in Model?

(as you said, an interface should not be defined
where it's implemented.)

or would they both go in a new class
Interfaces.cs

i tried that (Interfaces.cs) and it does work,
don't know if that's one of the ways you were suggesting?
thanks
mark
 
A

Arne Vajhøj

now that i've moved everything into the same project/assy
does the above still apply...if i replace
"yet another assembly,"
with
"yet another class"
???


If the interfaces are intended to be used be implemented
by classes in multiple assemblies - like if you want to
define some type of plugin/DI architecture, then it
must be in a separate assembly.

If the interface is only used to encapsulate the
implementing classes in the current assembly, then it
is not needed.

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top