[.NET] Remoting mbv interfaces

Pagina: 1
Acties:

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-04 22:46
Graag wil ik indien een event een event opgegooid wordt mbt een callback alle clients op de hoogte brengen van de update.

Eerst een interface, zodat ik op de client niet met meta data moet gaan lopen klooien:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
namespace IRemoteObjects
{
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    
    public delegate void QuestionChangedHandler();

    public interface IQuestionManager
    {       
        string GetPendingQuestion();
        void SubmitNewQuestion(string strQuestion);     

        event QuestionChangedHandler QuestionChangedEvent;
    }
}


Dan de implentatie....dit object wordt gehost middels een server applicatie, verder niet relevant voor het probleem:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using IRemoteObjects;

namespace RemoteObjects
{
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    
    //public delegate void QuestionChangedHandler();

    public class QuestionManager : MarshalByRefObject, IQuestionManager
    {
        private string _question;
        public event QuestionChangedHandler QuestionChangedEvent;

        public QuestionManager()
        {
            _question = "Undefined";
        }

        public QuestionManager(string strQuestion)
        {
            _question = strQuestion;            
        }

        public string GetPendingQuestion()
        {
            return _question;
        }

        public void SubmitNewQuestion(string strQuestion)
        {
            _question = strQuestion;
            this.QuestionChangedEvent();
        }
    }
}



Dan komen de problemen! Na op de client ook een remoting laag ingebouwd te hebben zou ik graag zodra in mijn remote object een event opgegooid wordt, de clients die hierdoor bediend worden reageren door bv de interface van een refresh te voorzien.

code:
1
m_RemoteObject.QuestionChangedEvent += new m_RemoteObject.QuestionChangedHandler(this.OnQuestionChanged);


Maar nu kan ik dus niet de Delegate aan zodat een callback mogelijk is?!? Hoe zou ik bovenstaande "moeten" realiseren. Naar mijn weten kan ik in een interface geen delegate meenemen, maar ergens zit dus mijn denkfout, iemand?

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Als die delegates bij die remote object zijn geregistreerd als listeners, dan kan je gewoon die delegate uitvoeren. Ik zou trouwens ook even kijken naar het proxy design pattern. Hierdoor kan je de 'remote' stap eigelijk een beetje negeren en kan je het eigelijk zien als lokale applicatie. En verder is het me niet helemaal duidelijk wat je nou bedoelt.

  • whitehouse
  • Registratie: Maart 2000
  • Laatst online: 27-03 12:23
Alarmnummer..
moet -=UTFS | RTFM =- niet zijn : -=RTFM|UTFM=- ???
eerst lezen.. DAN toepassen ;)

| www.everythingisspiritual.com | www.mosaic.org |


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Het ziet er eigenlijk wel goed uit wat je doet, maar ik volg je niet precies dus kan het niet helemaal goed bekijken waar je probleem zit. Met name dit is mij vrij onduidelijk:
Maar nu kan ik dus niet de Delegate aan zodat een callback mogelijk is?!? Hoe zou ik bovenstaande "moeten" realiseren. Naar mijn weten kan ik in een interface geen delegate meenemen, maar ergens zit dus mijn denkfout, iemand?
Ik heb dit zelf ook een keertje geimplementeerd. Misschien dat je daar iets aan hebt. Het ging hier om een simpel groupware systeem waarop je in kon loggen. Alle clients moeten op de hoogte worden gebracht als er iemand inlogt.

Dit is de interface voor de server:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System.Collections;
_
namespace JJM.GDOS.Groupware.Domain
{
  public interface IGroupwareCenter
  {
    IGroupwareHome Login(string username);
_
    IList OnlineUsers   { get; }
_
    event   UserEventHandler  OnlineUser;
    event   UserEventHandler  OfflineUser;
  }
_
  public delegate void UserEventHandler(object sender,  UserEventArgs e);
}


Dit is een simpele client:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private UserEventHandler onlineHandler;
private IGroupwareCenter center;
private IGroupwareHome home;
_
public Client(string[] parameters)
{
  center = (IGroupwareCenter)Activator.GetObject(typeof(JJM.GDOS.Groupware.Domain.IGroupwareCenter),
    "http://" + parameters[0] + ":" + parameters[1] + "/Groupware.NET/Center");
_
  onlineHandler = new UserEventHandler(OnlineUser);
  center.OnlineUser += onlineHandler;
_
  home = center.Login(parameters[2]);
}
_
public void Disconnect()
{
  Console.WriteLine("Removing the OnlineUserEventHandler");
  home.LogOff();
  center.OnlineUser -= onlineHandler;
}
_
public void OnlineUser(object sender,  UserEventArgs e)
{
  Console.WriteLine("{0} is online", e.User.Name);        
}


Je ziet dat de client zich hier dus 'gewoon' aanmeld op de server met behulp van een delegate en het event op de server. De implementatie van de server is niet zo spannend, maar ik kan hem wel posten als je hem graag wilt zien.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

C#:
1
m_RemoteObject.QuestionChangedEvent += new m_RemoteObject.QuestionChangedHandler(this.OnQuestionChanged);
Je instantieert een delegate die in het m_RemoteObject object is ondergebracht :?.
Die delegate staat toch in de IRemoteObjects namespace?

Volgens mij moet het zoiets worden waarbij de client de IRemoteObjects interface 'used':
C#:
1
m_RemoteObject.QuestionChangedEvent += new QuestionChangedHandler(this.OnQuestionChanged);

Verwijderd

Na wat nadenken vraag ik mij af of dit uberhaubt wel mogelijk is.

Objecten die worden aangemaakt via remoting worden aangemaakt in het server process. Nu weet ik het niet zeker, maar objecten worden in remoting volgens mij gepoold. Zodra je client weer het aangemaakte object aanspreekt, dan wordt er een object uit de pool gehaald, en gekoppeld aan de client. Dit is waarschijnlijk een heel ander object dan degene die in eerste instantie was geinstantieerd.

Ten tweede (wanneer het bovenste verhaal niet opgaat :P ) heb je te maken met de distributed garbage collection van .NET. Alle Marshall by Ref objecten hebben nl. een leasetime die er voor zorgt dat na het verstrijken, het object word opgeruimd door de garbage collector. Nu is dit nog wel op te lossen d.m.v. eigen leasetime's en sponsor's maar hier heb ik geen ervaring mee.

Waar je misschien ook naar kunt kijken zijn COM+ event sinks. Deze zijn ook specifiek voor dit doel gemaakt maar ik weet niet in hoeverre .NET dit support.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
ydejager: Dit is waarschijnlijk een heel ander object dan degene die in eerste instantie was geinstantieerd.
Dat hangt af van de WellKnownObjectMode waarmee je het WellKnownType registreert. Als deze mode een WellKnownObjectMode.Singleton, is er maar 1 instantie en dus altijd dezelfde instantie.

Het kan allemaal prima als het goed is, want ik heb het zelf geimplementeerd in het voorbeeld hierboven.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-04 22:46
ik zal ss ff mijn code uppen, want Martin... bij mij ziet het er ongeveer zo als bij jouw uit

[edit]
download de code hier

Zie de readme voor wat details.

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-04 22:46
Verwijderd schreef op 02 oktober 2002 @ 14:40:
C#:
1
m_RemoteObject.QuestionChangedEvent += new m_RemoteObject.QuestionChangedHandler(this.OnQuestionChanged);
Je instantieert een delegate die in het m_RemoteObject object is ondergebracht :?.
Die delegate staat toch in de IRemoteObjects namespace?

Volgens mij moet het zoiets worden waarbij de client de IRemoteObjects interface 'used':
C#:
1
m_RemoteObject.QuestionChangedEvent += new QuestionChangedHandler(this.OnQuestionChanged);
Ja ik zie net dat er wat stuntel code inzit...in dat zipje heb ik dat iig wel aangepast. Op de een of andere vreemde manier krijg ik hem niet aan de handler geregistreerd.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
paulgielens: ik zal ss ff mijn code uppen, want Martin... bij mij ziet het er ongeveer zo als bij jouw uit
Ik heb nu even geen tijd om code door te gaan wroeten, maar ik zal later vandaag even kijken als er nog geen oplossing is...

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Ik zit het even door te kijken en het valt mij op dat de OnQuestionChanged in de client methode private is (en bovendien niets doet). Zou dat geen problemen op kunnen leveren?

Verder ziet het er inderdaad wel goed uit.... Ik ben lui en had geen zin om m'n Microsoft Windows compu aan te zetten, dus heb het nog niet gedraaid. Wat gaat er eigenlijk precies mis op dit moment? Ik kan eventueel later de zaak nog wel ff draaien zodat ik wat gerichter kan zoeken naar het probleem...

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-04 22:46
ik heb de OnQuestionChanged ff public gemaakt, maar nog steeds...:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
See the end of this message for details on invoking 
just-in-time (JIT) debugging instead of this dialog box.

************** Exception Text **************
System.Runtime.Remoting.RemotingException: This remoting proxy has no channel sink which means either the server has no registered server channels that are listening, or this application has no suitable client channel to talk to the server.

Server stack trace: 
   at System.Runtime.Remoting.Proxies.RemotingProxy.InternalInvoke(IMethodCallMessage reqMcmMsg, Boolean useDispatchMessage, Int32 callType)
   at System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(IMessage reqMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at Client.Form1.OnQuestionChanged() in e:\demo projects\remotinginterfacing\client\form1.cs:line 151
   at RemoteObjects.QuestionManager.SubmitNewQuestion(String strQuestion) in e:\demo projects\remotinginterfacing\remoteobjects\questionmanager.cs:line 37
   at System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(MethodBase mb, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
   at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg, Int32 methodPtr, Boolean fExecuteInContext)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at IRemoteObjects.IQuestionManager.SubmitNewQuestion(String strQuestion)
   at Client.Form1.button2_Click(Object sender, EventArgs e) in e:\demo projects\remotinginterfacing\client\form1.cs:line 146
   at System.Windows.Forms.Control.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ButtonBase.WndProc(Message& m)
   at System.Windows.Forms.Button.WndProc(Message& m)
   at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


************** Loaded Assemblies **************
mscorlib
    Assembly Version: 1.0.3300.0
    Win32 Version: 1.0.3705.288
    CodeBase: file:///c:/windows/microsoft.net/framework/v1.0.3705/mscorlib.dll
----------------------------------------
Client
    Assembly Version: 1.0.0.0
    Win32 Version: 1.0.0.0
    CodeBase: file:///E:/Demo%20Projects/RemotingInterfacing/bin/Debug/Client.exe
----------------------------------------
System.Windows.Forms
    Assembly Version: 1.0.3300.0
    Win32 Version: 1.0.3705.288
    CodeBase: file:///c:/windows/assembly/gac/system.windows.forms/1.0.3300.0__b77a5c561934e089/system.windows.forms.dll
----------------------------------------
System
    Assembly Version: 1.0.3300.0
    Win32 Version: 1.0.3705.288
    CodeBase: file:///c:/windows/assembly/gac/system/1.0.3300.0__b77a5c561934e089/system.dll
----------------------------------------
System.Drawing
    Assembly Version: 1.0.3300.0
    Win32 Version: 1.0.3705.288
    CodeBase: file:///c:/windows/assembly/gac/system.drawing/1.0.3300.0__b03f5f7f11d50a3a/system.drawing.dll
----------------------------------------
System.Runtime.Remoting
    Assembly Version: 1.0.3300.0
    Win32 Version: 1.0.3705.288
    CodeBase: file:///c:/windows/assembly/gac/system.runtime.remoting/1.0.3300.0__b77a5c561934e089/system.runtime.remoting.dll
----------------------------------------
IRemoteObjects
    Assembly Version: 1.0.0.0
    Win32 Version: 1.0.0.0
    CodeBase: file:///E:/Demo%20Projects/RemotingInterfacing/bin/Debug/IRemoteObjects.DLL
----------------------------------------
System.Xml
    Assembly Version: 1.0.3300.0
    Win32 Version: 1.0.3705.288
    CodeBase: file:///c:/windows/assembly/gac/system.xml/1.0.3300.0__b77a5c561934e089/system.xml.dll
----------------------------------------

************** JIT Debugging **************
To enable just in time (JIT) debugging, the config file for this
application or machine (machine.config) must have the
jitDebugging value set in the system.windows.forms section.
The application must also be compiled with debugging
enabled.

For example:

<configuration>
    <system.windows.forms jitDebugging="true" />
</configuration>

When JIT debugging is enabled, any unhandled exception
will be sent to the JIT debugger registered on the machine
rather than being handled by this dialog.

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-04 22:46
Hmm, niemand die hier een antwoord op weet of wil weten?!?

Verwijderd

Ik zal vanavond wel even een proberen een testcase op te zetten. Ik ga er dus vanuit dat je MBR object een Singleton is?

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-04 22:46
Verwijderd schreef op 04 oktober 2002 @ 14:56:
Ik zal vanavond wel even een proberen een testcase op te zetten. Ik ga er dus vanuit dat je MBR object een Singleton is?
Remote object is singleton! Je kan de code gewoon downloaden als je wil... iig bedankt dat je even mee wil denken.

Verwijderd

Een beetje laat maar ik had net een nieuw boek over SQL Server binnen die ik niet links kon laten liggen :P.

Ik heb nog een oud test project weten te vinden die ik heb omgebouwd zodat er gebruik wordt gemaakt van een Singleton. Clients subscriben aan een event van het object in een serializable klasse ( hier ligt denk ik de clue ). Werkt prima bij mij. Je moet alleen even de goeie host in het remoting configuration XML bestand aanpassen.

Hier kun je de source vinden. Het gaat om remoting2.zip. Ik hoop dat je aan de hand hiervan de fout kunt vinden. Success!

/me ydejager gaat weer verder lezen :Y)

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-04 22:46
Ik heb eens gekeken maar de client crashed, maar daar kom ik wel uit. Een veel groter probleem met jouw voorbeeld is dat je dus geen interface gebruikt, maar de implementatie van de objecten zowel op de client als server hebt draaien. Dan is natuurlijk meteen het hele remoting concept naar de knoppen. Mijn probleem is nu net... om TCP te kunnen gebruiken MOET je wel interfaces gebruiken, anders moet je naar meta data toe via SOAP. Nou is mijn probleem om op de client events op te kunnen vangen welke door de server opgegooid worden. LET OP: de client zou bv een aanroep kunnen doen op de server welke een event opgooid, zodat dezelfde client ook weer het event opvangt etc

iig bedankt, wellicht dat ik er alsnog uitkom t.z.t.

Verwijderd

Ik heb een nieuwe versie geupload (remoting3.zip) welke gebruik maakt van interfaces. De truuk was de implementatie van het event in de klasse. Dit was een syntax die ik nog niet eerder was tegengekomen:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public delegate void StatusEvent();

public interface IInterface
{
    event StatusEvent Status;
}

public class Blaat : MarshalByRefObject, IInterface
{
    private StatusEvent _status;

    event StatusEvent IInterface.Status
    {
        add
        {
            _status += value;
        }

        remove
        {
            _status -= value;
        }
    }
}

Een soort properties dus. Deze syntax kwam niet in mijn C# bijbel voor (die gebruikte nog de beta van .NET :) ).

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-04 22:46
Eens kijken, bedankt!
Pagina: 1