| 

.NET C# Java Javascript Exception

2
Wie kann ich in einer Klasse eine Variable definieren, die in anderen Klassen verfügbar ist.
public class A
{
public MyObject MyObject { get; set; };
public void Validate(string userName, string password)
{
MyObject = GetMyObject(userName, password);
}
}

public class B
{
//hier die gesetzte Variable "MyObject" aus Klasse A verwenden
}


Die Klasse A wird an einer anderen Stelle instanziiert (Authentifizierung) und kann nicht in Klasse B neu instanziiert werden!

Ich habe einen Tipp bekommen, diese in den aktuellen Thread zu schreiben. Hat jemand ein Beispiel, wie man so ein Szenario realisieren kann? Oder eine komplett andere Idee?
16.03.2011
Mario Priebe 6,0k 3 9
3 Antworten
1
Als erstes würde mir das Singleton-Pattern für Klasse A einfallen. (Mein persönlicher Favorit :o))

Eine weitere Möglichkeit wäre, MyObject statisch zu machen.

class Program
{
static void Main(string[] args)
{
A a = new A();
a.Validate("", "");
B b = new B();

}
}

public class A
{
public static string MyObject { get; set; }
public void Validate(string userName, string password)
{
MyObject = "xy";
}
}


public class B
{
public B()
{
Console.WriteLine(A.MyObject);
}
}


Hier wäre noch die Singleton-Variante:
class Program
{
static void Main(string[] args)
{
A.GetInstance.Validate("user", "pw");
B b = new B();
}
}

public class A
{
private A()
{
}

public static A GetInstance
{
get
{
return Nested.Instance;
}
}

class Nested
{
static Nested()
{
}

internal static readonly A Instance = new A();
}

public string MyObject { get; private set; }
public void Validate(string userName, string password)
{
MyObject = "xy";
}
}


public class B
{
public B()
{
Console.WriteLine(A.GetInstance.MyObject);
}
}


MyObject müsste dann natürlich wieder vom entsprechenden Typ sein. Für das Beispiel habe ich string genommen. Zudem sollte MyObject nicht ohne "Validate" überschreibbar sein. Daher habe ich noch ein "private" dem Setter beim Property "MyObject" hinzugefügt.

Ich würde das Singleton verwenden, um mehrere Instanzen von A zu vermeiden.

Kleiner Anhang zum Singleton-Pattern:
Hier werden die unterschiedlichen Singleton-Patterns erklärt: Implementing the Singleton Pattern in C# Ich verwende die "Fifth version - fully lazy instantiation"
16.03.2011
Jürgen Luhr 7,1k 1 9
Die statische Variante gefällt +1, gibt es Probleme wenn mehrere verschiedene Clients den Service benutzen und die statische Variable beschreiben? Ich muss dazu erwähnen, dass sich in dieser Variable (MyObject)Authentifizierungsinformationen befinden.
Mario Priebe 16.03.2011
Nachfrage: Der Code läuft schon auf dem Client, oder? Der Server muss ja zustandslos sein.
Jürgen Luhr 16.03.2011
jep, genauso ist es.
Mario Priebe 16.03.2011
sorry, werde gerade aus Euren Kommentaren nicht schlau: der Code (d.h. inklusive der statischen Variable!?) läuft auf dem Client, aber Mario sorgt sich, dass verschiedene Clients in Konflikt geraten könnten?
Matthias Hlawatsch 16.03.2011
@Matthias: Aus seinen bisherigen Fragen gehe ich davon aus, dass er eine Authentifizierung über SOAP evt. mit dem SOAP-Header macht, die Benutzerinformationen einmalig einliest und bei jedem Service-Aufruf diese Benutzerinformationen mitgibt.
@Mario: Die Clients besitzen alle eine eigene Client-Instanz und können nicht in Konflikt geraten.
Jürgen Luhr 16.03.2011
@Jürgen: ok, wenn das so ist, dann ist das Singleton-Pattern hier völlig ausreichend (und meine Lösung, s.u., Overkill). Kannst Du noch kurz erklären, wofür Du die nested class brauchst, statt Instance direkt in A unterzubringen?
@Mario: Dein erster Kommentar hat mich verwirrt: verschiedene Clients = verschiedene Prozesse = kein Problem. Aber nimm die Singleton-Lösung. Eine statische Property aus einer Instanzmethode der selben Klasse heraus zu verändern wäre für mich eher ein code smell.
Matthias Hlawatsch 16.03.2011
Durch die Schachtelung (nested class) kann die Threadsicherheit ohne Lock() sichergestellt werden,denn wenn auf eine Instanzeigenschaft zugegriffen wird, dann wird per nested class immer auf die selbe Instanz zugegriffen.
Jorgen Schumann 16.03.2011
@Matthias: Jorgen hat es schon erklärt. Ich habe diesbezüglich meine Antwort erweitert.
Jürgen Luhr 16.03.2011
Besten Dank Euch! (die Frage könnte man doch eigentlich auch bewerten, oder ;))
Mario Priebe 17.03.2011
Ja klar ;o) +1
Jürgen Luhr 17.03.2011
1
Vielleicht im Konstruktor von B ein Objekt der Klasse A übergeben oder einfach nur MyObject und das dann einem Member oder einem private Field von Klasse B zuweisen ? Wär jetzt mal eine Idee aber sicher bin ich mir auch nicht.
16.03.2011
Das geht leider nicht, weil ich in Klasse B die Informationen zu MyObjekt nicht habe bzw. sehr viele bestehende Instanziierungen erweitern müsste.
Mario Priebe 16.03.2011
1
Da Du Authentifizierung angesprochen hast, auch erst neulich nach WCF-Authentifizierung gefragt hast und das Thread-Thema ansprichst, vermute ich mal, dass Dir eine "globale Variable" (öffentliche statische Property in A oder sonstwo) nicht reicht, weil es potentiell mehrere zu unterscheidende Instanzen von MyObject gleichzeitig gibt. Vermutlich wird dann auch eine Dependency-Injection (B bekommt A im Konstruktor) nicht passen (falls doch: mach es so).

Dann wäre tatsächlich noch Thread-local storage eine Überlegung wert. Dazu gibt es vor NET 4 zwei, danach sogar noch eine dritte Möglichkeit. Siehe

AllocateNamedDataSlot

mit diesem Beispiel,

ThreadStaticAttribute

und

ThreadLocal<T>

Wenn Du schließlich den Wert von MyObjects in verschiedenen Threads verschieden setzen können willst, danach aber an untergeordnete Threads weiterreichen willst, dann schau Dir die Klasse CallContext an. Damit habe ich selbst schon mal die Info über den User in einemm WCF-Service gehalten: Eine kleine Wrapper-Klasse mit einer Property, die in getter/setter auf Context.GetLocalData bzw. Context.SetLocalData delegiert, beim Aufruf des Service den User setzen (mit einem WCF-Behavior, wenn ich mich recht entsinne) und später, wo immer er gebraucht wurde, auf den User zugegriffen - im guten Gefühl, dass es der User ist, der zum gerade bearbeiteten Service-Aufruf gehört und nicht etwa zu einem, der parallel in einer anderen Instanz bearbeitet wird.
16.03.2011
Matthias Hlawatsch 13,2k 4 9

Stelle deine .net-Frage jetzt!