Frage

Ich glaube nicht, das möglich ist, aber wenn dann brauche ich es:)

Ich habe eine automatisch generierte Proxy-Datei aus dem wsdl.exe Kommandozeilen-Tool von Visual Studio 2008.

Der Proxy-Ausgang sind Teilklassen. Ich möchte den Standard-Konstruktor außer Kraft zu setzen, die generiert wird. Ich möchte nicht den Code ändern, da sie automatisch generiert wird.

Ich habe versucht, einen anderen Teil-Klasse zu machen und den Standard-Konstruktor neu zu definieren, aber das funktioniert nicht. Ich habe dann versucht, mit der Überschreibung und neue Keywords, aber das funktioniert nicht.

Ich weiß, dass ich von der partiellen Klasse erben könnte, aber das würde bedeuten, ich müsste alle unsere Quellcode ändern, um die neue übergeordnete Klasse zu zeigen. Ich möchte nicht, dies zu tun haben.

Alle Ideen, Workarounds oder Hacks?

//Auto-generated class
namespace MyNamespace {
   public partial class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol {
      public MyWebService() {
         string myString = "auto-generated constructor";
         //other code...
      }
   }
}

//Manually created class in order to override the default constructor
namespace MyNamespace {
   public partial class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol {
      public override MyWebService() { //this doesn't work
         string myString = "overridden constructor";
         //other code...
      }
   }
}
War es hilfreich?

Lösung

Dies ist nicht möglich. Partielle Klassen sind im wesentlichen Teile der gleichen Klasse; keine Methode kann zweimal oder außer Kraft gesetzt definiert werden, und das schließt den Konstruktor.

Sie können ein Verfahren, in dem Konstruktor aufrufen, und es nur im anderen Teil-Datei implementieren.

Andere Tipps

Ich hatte ein ähnliches prolem, mit meinem generierten Code durch eine dbml Datei erstellt wird (ich usng Linq-to-SQL-Klassen).

In der generierten Klasse eine partielle Leere nennt OnCreated () am Ende des Konstruktor aufgerufen.

Lange Rede kurzer Sinn, wenn Sie die wichtigen Konstruktor Sachen die generierte Klasse für Sie tut behalten wollen (was Sie wahrscheinlich tun sollte), dann in der partiellen Klasse erstellen die folgenden:

partial void OnCreated()
{
    // Do the extra stuff here;
}

Hmmm, Ich denke, eine elegante Lösung wäre die folgende:

//* AutogenCls.cs file
//* Let say the file is auto-generated ==> it will be overridden each time when
//* auto-generation will be triggered.
//*
//* Auto-generated class, let say via xsd.exe
//*
partial class AutogenCls
{
    public AutogenCls(...)
    {
    }
}



//* AutogenCls_Cunstomization.cs file
//* The file keeps customization code completely separated from 
//* auto-generated AutogenCls.cs file.
//*
partial class AutogenCls
{
    //* The following line ensures execution at the construction time
    MyCustomization m_MyCustomizationInstance = new MyCustomization ();

    //* The following inner&private implementation class implements customization.
    class MyCustomization
    {
        MyCustomization ()
        {
            //* IMPLEMENT HERE WHATEVER YOU WANT TO EXECUTE DURING CONSTRUCTION TIME
        }
    }
}

Dieser Ansatz hat einige Nachteile (wie alles):

  1. Es ist nicht klar, wann genau den Konstruktor der MyCustomization inneren Klasse während gesamten Bauablauf der AutogenCls Klasse ausgeführt werden.

  2. Wenn es notwendig sein wird, IDiposable Schnittstelle für die MyCustomization Klasse korrekt zu implementieren, um die Entsorgung von nicht verwalteten Ressourcen der MyCustomization Klasse zu behandeln, ich weiß es (noch) nicht, wie die MyCustomization.Dispose auslösen () -Methode ohne berühren der AutogenCls.cs Datei ... (aber wie ich 'noch' gesagt:)

Aber dieser Ansatz bietet große Trennung von automatisch generierten Code -. Ganzer Anpassung wird in verschiedener src-Code-Datei getrennt

genießen:)

Eigentlich ist dies nun möglich, jetzt, wo Teil Methoden hinzugefügt wurden. Hier ist die doc:

http://msdn.microsoft.com/en-us/library/ wa80x488.aspx

Im Grunde ist die Idee, dass Sie eine Methode in einer Datei deklarieren und aufrufen können, wo Sie die Teil-Klasse definieren, aber nicht wirklich die Methode in dieser Datei definieren. In der anderen Datei können Sie das Verfahren dann definieren. Wenn Sie eine Baugruppe bauen, wo das Verfahren nicht definiert ist, dann entfernt das ORM alle Anrufe an die Funktion.

So im Fall darüber würde wie folgt aussehen:

// Auto-generierte Klasse

namespace MyNamespace {
   public partial class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol {
      public MyWebService() {
         string myString = "auto-generated constructor";
         OtherCode();
      }
   }
}

partial void OtherCode();

// Manuell erstellte Klasse, um den Standard-Konstruktor außer Kraft zu setzen

partial void OtherCode()
{
   //do whatever extra stuff you wanted.
}

Es ist etwas begrenzt, und in diesem speziellen Fall, in dem Sie eine generierte Datei, die Sie ändern müssen, würde es vielleicht nicht die richtige Lösung sein, aber für andere, die auf diese versuchen, stolperte Funktionalität in Teilklassen außer Kraft zu setzen dies kann sehr hilfreich sein.

Das Problem, das die OP bekommen hat, ist, dass die Web-Referenz-Proxy erzeugt keine Teil-Methoden, die Sie verwenden können, den Konstruktor abzufangen.

ich in das gleiche Problem lief, und ich kann WCF nicht nur aktualisieren, da der Webservice, dass ich Targeting es nicht unterstützt.

Ich möchte nicht manuell den automatisch generierten Code ändern, weil es abgeflacht erhalten, wenn jemand jemals die Code-Generierung aufruft.

ich in Angriff genommen, das Problem aus einem anderen Blickwinkel. Ich wusste, dass meine Initialisierung vor einem Antrag erforderlich machen, es hat nicht wirklich Bauzeit fertig werden müssen, so dass ich overrode nur die GetWebRequest Methode, wie so.

protected override WebRequest GetWebRequest(Uri uri)
{
    //only perform the initialization once
    if (!hasBeenInitialized)
    {
        Initialize();
    }

    return base.GetWebRequest(uri);
}

bool hasBeenInitialized = false;

private void Initialize()
{
    //do your initialization here...

    hasBeenInitialized = true;
}

Dies ist eine schöne Lösung, weil es nicht verwickeln sich Hacker der Auto-Code erzeugt, und sie paßt den genauen Anwendungsfall des OP der Initialisierung Login für einen Soaphttpclientprotocol automatisch generierten Proxy durchführen.

Sie können dies nicht tun. Ich schlage vor, eine Teil-Methode verwendet, die Sie dann eine Definition für erstellen können. So etwas wie:

public partial class MyClass{ 

    public MyClass(){  
        ... normal construction goes here ...
        AfterCreated(); 
    }

    public partial void OnCreated();
}

Der Rest sollte ziemlich selbsterklärend sein.

EDIT:

Ich möchte auch darauf hinweisen, dass Sie sollten eine Schnittstelle für diesen Dienst werden definiert, die Sie dann Programm, so dass Sie sich keine Hinweise auf die tatsächliche Umsetzung haben. Wenn du das getan hast, dann würde man ein paar andere Optionen haben.

Ich denke man könnte in der Lage sein, dies zu tun mit Postsharp , und es sieht aus wie jemand gerade getan hat was Sie in generierten Teilklassen für Methoden wollen . Ich weiß nicht, ob dies ohne weiteres auf die Fähigkeit übersetzen wird, ein Verfahren zu schreiben und seinen Körper den Konstruktor ersetzen, wie ich es nicht einen Schuss noch gegeben haben, aber es scheint einen Versuch wert.

Edit: dies auf der gleichen Linie und sieht auch interessant.

Dies ist meiner Meinung nach einem Designfehler in der Sprache. Sie haben sollten mehrere Implementierungen von einem Teilverfahren erlaubt, die eine schöne Lösung zur Verfügung gestellt hätte. In einer noch schöneren Art und Weise der Konstruktor (auch ein Verfahren) kann dann auch einfach Teil- und mehrere Konstrukteure mit der gleichen Signatur markiert werden würde ausgeführt werden, wenn ein Objekt zu schaffen.

Die einfachste Lösung ist wahrscheinlich einen Teil ‚Konstruktor‘ Methode für jede zusätzliche Teil Klasse hinzuzufügen:

public partial class MyClass{ 

    public MyClass(){  
        ... normal construction goes here ...
        OnCreated1(); 
        OnCreated2(); 
        ...
    }

    public partial void OnCreated1();
    public partial void OnCreated2();
}

Wenn Sie die Teilklassen wollen umeinander Agnostiker sein, können Sie Reflexion verwenden:

// In MyClassMyAspect1.cs
public partial class MyClass{ 

    public void MyClass_MyAspect2(){  
        ... normal construction goes here ...

    }

}

// In MyClassMyAspect2.cs
public partial class MyClass{ 

    public void MyClass_MyAspect1(){  
        ... normal construction goes here ...
    }
}

// In MyClassConstructor.cs
public partial class MyClass : IDisposable { 

    public MyClass(){  
       GetType().GetMethods().Where(x => x.Name.StartsWith("MyClass"))
                             .ForEach(x => x.Invoke(null));
    }

    public void Dispose() {
       GetType().GetMethods().Where(x => x.Name.StartsWith("DisposeMyClass"))
                             .ForEach(x => x.Invoke(null));
    }

}

Aber eigentlich sollte sie fügen Sie einfach einige weitere Sprachkonstrukte mit Teilklassen zu arbeiten.

Für ein Web-Service-Proxy generiert von Visual Studio, können Sie Ihren eigenen Konstruktor in der Teilklasse nicht hinzufügen (gut können Sie, aber es ist nicht genannt bekommt). Stattdessen können Sie die Verwendung [OnDeserialized] Attribut (oder [OnDeserializing]) an der Stelle in Ihrem eigenen Code einzuhaken, wo der Web-Proxy-Klasse instanziiert wird.

using System.Runtime.Serialization;

partial class MyWebService
{
     [OnDeserialized]
     public void OnDeserialized(StreamingContext context)
     {
         // your code here
     }
}

Manchmal haben Sie keinen Zugang oder es ist nicht der Standard-Konstruktor zu ändern erlaubt, aus diesem Grund Sie nicht den Standard-Konstruktor haben können alle Methoden aufrufen.

In diesem Fall, dass Sie einen anderen Konstruktor mit einem Dummy-Parameter erstellen können, und machen diesen neuen Konstruktor den Standardkonstruktor aufrufen mit „: diese ()“

public SomeClass(int x) : this()
{
    //Your extra initialization here
}

Und wenn Sie eine neue Instanz dieser Klasse erstellen geben Sie nur Dummy-Parameter wie folgt aus:

SomeClass objSomeClass = new SomeClass(0);

Nichts, was ich mir vorstellen kann. Die „besten“ Weg ich mit oben kommen kann ist ein Ctor mit einem Dummy-Parameter hinzuzufügen und zu verwenden:

public partial class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol 
{
   public override MyWebService(int dummy) 
   { 
         string myString = "overridden constructor";
         //other code...
   }
}


MyWebService mws = new MyWebService(0);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top