Delegates or events ?

  • Thread starter Thread starter GTi
  • Start date Start date
G

GTi

[now with correct date and time]

I have this solution:

[File A - WIndows EXE] -> [File B - LIB DLL] -> [File C - Plugin DLLs]

A knows about B but not C
C knows about B but not A

Type A can be a EXE file or NT Service
There can be many of type A loaded but not necessarily the same file.

Type C is a plugin that is loaded by A on runtime.
There can be many of type C available but not necessarily the same file.

Now the problem.
A have a status window giving the end user status of the program.
The status is given by C.
So I think I must implement a interfaces in B and implment it into A and C.
C send statuses to B and use A as subscribber to events/delegates from B.

But I have problem understanding how this can be done.
 
GTi said:
[now with correct date and time]

I have this solution:

[File A - WIndows EXE] -> [File B - LIB DLL] -> [File C - Plugin DLLs]

A knows about B but not C
C knows about B but not A

Type A can be a EXE file or NT Service
There can be many of type A loaded but not necessarily the same file.

Type C is a plugin that is loaded by A on runtime.
There can be many of type C available but not necessarily the same file.

Now the problem.
A have a status window giving the end user status of the program.
The status is given by C.
So I think I must implement a interfaces in B and implment it into A and C.

I don't think you'll need to implement the interface in A - A will just
*use* the interface, I suspect.
C send statuses to B and use A as subscribber to events/delegates from B.

But I have problem understanding how this can be done.

Well, you'll need a "custom" delegate in B if none of the ones in the
standard framework are suitable. Either way, your interface should
contain the event, so that A can subscribe to the events without
knowing the details of what the implementation is.

I'll try to write a quick sample later on, if that would help.

Jon
 
Jon Skeet said:
GTi said:
[now with correct date and time]

I have this solution:

[File A - WIndows EXE] -> [File B - LIB DLL] -> [File C - Plugin DLLs]

A knows about B but not C
C knows about B but not A

Type A can be a EXE file or NT Service
There can be many of type A loaded but not necessarily the same file.

Type C is a plugin that is loaded by A on runtime.
There can be many of type C available but not necessarily the same file.

Now the problem.
A have a status window giving the end user status of the program.
The status is given by C.
So I think I must implement a interfaces in B and implment it into A and
C.

I don't think you'll need to implement the interface in A - A will just
*use* the interface, I suspect.
C send statuses to B and use A as subscribber to events/delegates from B.

But I have problem understanding how this can be done.

Well, you'll need a "custom" delegate in B if none of the ones in the
standard framework are suitable. Either way, your interface should
contain the event, so that A can subscribe to the events without
knowing the details of what the implementation is.

I'll try to write a quick sample later on, if that would help.

Jon

Jon,
I can't wait for a quick sample.
Maybe I can then understand the missing bit.
 
Hi,
A knows about B but not C
C knows about B but not A

This is correct, in B you will declare the interfaces that both A & C will
implement/use
Type A can be a EXE file or NT Service
Does not matter, except that the service cannot have a console window
There can be many of type A loaded but not necessarily the same file.

Not clear of what this means, are you refering that you may load several
instances of A (under different service names I assume) or you mean that
there several projects that conform to A description?

Type C is a plugin that is loaded by A on runtime.
There can be many of type C available but not necessarily the same file.

Not a problem, you load the DLL dynamically and handle the instance using
the interfaces declared in B , see Jon's plugin article.
Now the problem.
A have a status window giving the end user status of the program.

Note that a service should not have interaction with the desktop, so in this
case is better to use the eventlog
The status is given by C.
So I think I must implement a interfaces in B and implment it into A and
C.
C send statuses to B and use A as subscribber to events/delegates from B.

No really, You declare an interface in B , C has a class that implement this
interface and you use it from A.

Here I wrote how it may looks like, note that I wrote it here so it WILL
NOT compile for sure !!!
But I hopoe you will get the idea of how it's done.

Like:
IN B
interface ILog {
EventHandler event GotNewNotif;
public string theNotif;
}

IN C:
Public class theClass: ILog{
public EventHandler event GotNewNotif ;
public string theNotif;

private void SendNotif()
{
theNotif = " sdfas fas fawqr qwr";
GotNewNotif( this, null);
}
}


In A:
class Class
{
void GotMotif( object sender, EventArgs e)
{
Console.Write( ((ILog)sender).theNotif );
}

void WireAll()
{

Assemble a = Assembly.LoadFromFile(
Configuration.AppSettings["c_file_source"] );
ILog l = (ILog) a.CreateInstance(
Configuration.AppSettings["what_class_to_create"] );
l.GotNewNotif += new EventHandler( GotNotif);
}
}
 
GTi said:
I can't wait for a quick sample.
Maybe I can then understand the missing bit.

Okay, here it is:

A.cs: (The "driver" class)
using System.Reflection;

public class MainApp
{
static void Main(string[] args)
{
foreach (string x in args)
{
Assembly assm = Assembly.Load(x);

foreach (Type t in assm.GetTypes())
{
if (typeof(IPlugin).IsAssignableFrom(t))
{
IPlugin plugin=(IPlugin)Activator.CreateInstance(t);
plugin.Notification += new EventHandler(WriteArgs);
plugin.Start();
}
}
}
}

static void WriteArgs(object sender, EventArgs e)
{
Console.WriteLine (e.ToString());
}
}

B.cs: (The interface)
using System;

public interface IPlugin
{
event EventHandler Notification;

void Start();
}

C.cs: (The plugins)
using System;
using System.Threading;

// Plugin1 fires the notification event once a second for
// 10 seconds
public class Plugin1 : IPlugin
{
// Using field-like events for simplicity
public event EventHandler Notification;

public void Start()
{
new Thread(new ThreadStart(ThreadEntry)).Start();
}

void ThreadEntry()
{
for (int i=0; i < 10; i++)
{
Notification(this, new NamedArg("Plugin1"));
Thread.Sleep (1000);
}
}
}

// Plugin2 just fires the notification event once
// and stops
public class Plugin2 : IPlugin
{
// Using field-like events for simplicity
public event EventHandler Notification;

public void Start()
{
Notification(this, new NamedArg("Plugin2"));
}
}

class NamedArg : EventArgs
{
string name;

internal NamedArg (string name)
{
this.name = name;
}

public override string ToString()
{
return name;
}
}



Compiling from the command line:
csc /target:library B.cs
csc /target:library C.cs /r:B.dll
csc A.cs /r:B.dll

Then run it with
A.exe C
 

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

Similar Threads


Back
Top