Frage

Ich habe eine Situation, in der ich mein Modell und Implementierung bin versucht zu halten, so locker wie möglich verbunden ist, aber ich mit einer Situation konfrontiert bin, wo die Kupplung möglicherweise sehr viel näher kommen könnte, als ich will.

Ich habe eine Auswahl von ‚Model‘ Klassen, alle Durchführungs Schnittstellen. Zusätzlich habe ich Klassen ‚Data Access‘, die eine Reihe von Funktionen zur Verfügung stellen, von denen eine ganze Zahl Nachschlagewerte in ihrer vollen ‚Objekt‘ Darstellung decodiert.

Im Rahmen meiner Modellklassen Ich möchte den Zugriff auf diese decodierten Werte schaffen, ohne das Modell erfordert über die Datenzugriffsklassen kennen.

Ein vereinfachtes Beispiel ist:

/// Core classes --

class Car : ICar
{
    public int MakeId { get {...} set { ... } }

    public IMakeInfo Make { get {...} }

    public string Registration { get { ... } set { ... } }

    public int CurrentOwnerId { get { ... } set { ... } }

    public IPerson CurrentOwner { get { ... } }
}

class MakeInfo : IMakeInfo
{
    public string Name { ... }
    public int Id { ... }
    public decimal Weight { ... }
    // etc etc
}

/// Data Access Classes --

class ResolveMake 
{
    public IMakeInfo GetMakeInfo(int id)
    { 
        // Implementation here...
    }

}

Wie kann ich die Car Klasse ermöglichen, die IMakeInfo Objekt zu irgendwelchen raubend Klassen zu schaffen, ohne direkt macht es sich der ResolveMake Klasse? In der aktuellen Instanz mit der Car-Klasse arbeite ich nicht im gleichen Namensraum wie die ResolveMake Klasse und es enthält keine Verweise auf alle Instanzen davon.

Einige meiner Optionen:

  • Implementieren eines Stellvertreters in Car, die mit einer Instanz der GetMakeInfo Verfahren zugeführt werden kann.
  • Eine Art Dependency Injection
  • Eng Paar Autos zu ResolveMake und mit ihm getan werden.
  • Alle anderen Optionen?

Alle Vorschläge willkommen!

War es hilfreich?

Lösung

Erweiterungsmethoden ?

namespace CarStuff
{
   class Car : ICar
   {
      public int MakeId { get {...} set { ... } }
      // no Make property...
      public string Registration { get { ... } set { ... } }
      public int CurrentOwnerId { get { ... } set { ... } }
      public IPerson CurrentOwner { get { ... } }
   }
}


namespace MakeExts
{
   class ResolveMake
   {
      public static IMakeInfo Make(this Car myCar)
      {
         //implementation here
      }
   }
}

an anderer Stelle:

using MakeExts;

Car c = new Car();
Console.WriteLine(c.Make().ToString());

Edit: Für die Verwendung von Erweiterungsmethoden in .NET 2.0, benötigen Sie so etwas wie:

Im Grunde eine Klasse enthält:

namespace System.Runtime.CompilerServices 
{ 
   class ExtensionAttribute : Attribute
   {
   }
 }

und verstreut in relevanten Stellen "System.Runtime.CompilerServices mit".

Andere Tipps

Es klingt wie Dependency Injection zu mir. Ich habe ähnliche Dinge mit MS PP Einheit und sowohl contructor Injektion sowie Verfahren und Eigentum Injektion erfolgen. Dann wird Ihr Auto-Klasse würde irgendeine Art von Injektion des IMakeInfo ... Beispiel haben:

[InjectionMethod]
public void Initialize([Dependency] IMakeInfo makeInfo)
{
  this.MakeInfo = makeInfo;
}

Da die Car-Klasse eine Eigenschaft hat, die Make IMakeInfo kehrt sieht aus wie es bereits die Informationen zur Verfügung stellt. So ist ich recht in der Annahme, dass Ihr Problem ist, wie das Auto mit dem Wert versehen ist, zurückzukehren?

Wenn dies der Fall ist, vielleicht Sie ein Factory-Methode zu schaffen aussehen wollen, die wissen, über Autos und ResolveMake.

mit Ihrer Analogie geht, muss das Auto offensichtlich durch die Zeit wissen, get_Make genannt wird, was der IMakeInfo ist. Ich würde auch die Marke ein wesentliches Merkmal des Autos berücksichtigen. Deshalb denke ich, eine IMakeInfo an das Auto Konstruktor (möglicherweise mit IOC) sehr sinnvoll ist. Ist dies eine gute Analogie zu Ihrem echten Code ist (jeder „Car“ hat ein einziges, intrinsisches „IMakeInfo“), würde ich mit diesen gehen.

Sie können auch einen Setter verwenden wie Johan sagte, wieder mit optionalem IOC. Der Grund, warum ich einen Konstruktor bevorzugen würde, ist, dass es scheint, alle „Car“ sollte ein „Make“ haben.

Am Ende (die Einschränkungen I innerhalb arbeiten) habe ich tatsächlich eine Variation eine Reihe der oben genannten Themen.

Weil ich hatte alle Verweise auf meine Datenzugriffsschicht zu vermeiden, aufgrund zirkuläre Referenzen auftretende ich etwas zu tun mit den Delegierten am Ende und die ‚Fabrik‘ Code. Montage es in meiner ursprünglichen Szenario habe ich die folgenden:

class Car 
{
    public void SetLookupProvider(ILookupProvider value) { _lookupProvider = value; }

    public IMakeInfo Make { get { return _lookupProvider.ResolveMake(MakeId); } }

    ....
}

interface ILookupProvider
{
    IMakeInfo ResolveMake(int id);
}

class LookupProvider
{
    public delegate IMakeInfo ResolveMakeDelegate(int id);

    public ResolveMakeDelegate ResolveMakeDel { set { _resolvemake = value; } }

    public IMakeInfo ResolveMake(int id){ return _resolvemake(id); }  
}

Dann in meiner Fabrik Methode ...

ICar returnedObject = new Car(blah, foo, bar, etc);

ILookupProvider luprovider = new LookupProvider();
luprovider.ResolveMakeDel = DataAccessLayer.FunctToGetMakeInfo;

(Car)returnedObject.SetLookupProvider(luprovider).

Jetzt bin ich die erste, die zugibt, dass dies nicht die schönste Lösung (I mit Erweiterungsmethoden gegangen wäre, hatte mich auf einen 3.0-Compiler zugreifen ..), aber es macht die Car-Klasse hält lose mit dem Data Access Schicht gekoppelt (die in meiner Situation zirkulären Verweis Hölle verhindert ...). Die Car-Klasse braucht nicht zu wissen, wie es das Ergebnis und die Factory-Methode wird immer, die die Auto-Objekte in erster Linie produziert wird, um die einzige Sache, das an die Datenzugriffsschicht gekoppelt ist.

Ich habe noch keine Antwort markiert, ich werde ein paar mehr Leute wählen lasse dann mit dem höchsten gehen - vor allem, da ich denke, dass sie alle gültigen Antworten sind (es ist nur, dass ich nicht ein in Teilen verwenden könnte in diese Instanz).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top