문제

나는 이것이 가능하다고 생각하지 않지만, 그렇다면 필요합니다 :)

Visual Studio 2008의 wsdl.exe 명령 줄 도구에서 자동 생성 된 프록시 파일이 있습니다.

프록시 출력은 부분 클래스입니다. 생성 된 기본 생성자를 무시하고 싶습니다. 코드가 자동으로 생성되었으므로 코드를 수정하지 않습니다.

다른 부분 클래스를 만들고 기본 생성자를 재정의하려고 시도했지만 작동하지 않습니다. 그런 다음 재정의와 새 키워드를 사용해 보았지만 작동하지 않습니다.

나는 부분 클래스에서 상속 될 수 있다는 것을 알고 있지만, 새로운 상위 클래스를 가리 키도록 모든 소스 코드를 변경해야한다는 것을 의미합니다. 차라리 그렇게 할 필요가 없습니다.

아이디어, 작업 또는 해킹이 있습니까?

//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...
      }
   }
}
도움이 되었습니까?

해결책

이건 불가능 해. 부분 클래스는 본질적으로 동일한 클래스의 일부입니다. 방법을 두 번 정의하거나 재정의 할 수 없으며 생성자가 포함됩니다.

생성자에서 메소드를 호출하고 다른 부분 파일에서만 구현할 수 있습니다.

다른 팁

비슷한 프롤렘이 있었는데, DBML 파일 (USNG LINQ-to-SQL 클래스)에 의해 생성 된 코드가 생성됩니다.

생성 된 클래스에서는 생성자 끝에 oncreated () 호출 된 부분 공극을 호출합니다.

간단히 말해서, 중요한 생성자 물건을 유지하려면 생성 된 클래스가 당신을 위해하는 것 (아마도 당신이해야 할 일)을 유지하려면 부분 클래스에서 다음을 만듭니다.

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

흠, 우아한 솔루션 중 하나는 다음과 같은 것 같습니다.

//* 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
        }
    }
}

이 접근법에는 몇 가지 단점이 있습니다 (모든 것).

  1. AutoGencls 클래스의 전체 구성 절차 중에 MyCustomization 내부 클래스의 생성자가 정확히 실행되는시기는 확실하지 않습니다.

  2. MyCustomization 클래스의 MyCustomization 클래스의 관리되지 않는 리소스 처분을 올바르게 처리하기 위해 MyCustomization 클래스에 idiposable 인터페이스를 구현 해야하는 경우 MyCustomization.dispose () 메소드를 autogencls.cs 파일을 터치하지 않는 방법을 모르겠습니다. ... (하지만 아직 '말한 것처럼 :)

그러나이 접근법은 자동 생성 코드와 큰 분리를 제공합니다. 전체 사용자 정의는 다른 SRC 코드 파일에서 분리됩니다.

즐겨 :)

실제로, 이것은 이제 가능합니다. 이제 부분 방법이 추가되었습니다. 다음은 문서입니다.

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

기본적으로 아이디어는 부분 클래스를 정의하는 한 파일의 메소드를 선언하고 호출 할 수 있지만 실제로 해당 파일의 메소드를 정의하지는 않습니다. 다른 파일에서는 메소드를 정의 할 수 있습니다. 메소드가 정의되지 않은 어셈블리를 구축하는 경우 ORM은 함수에 대한 모든 호출을 제거합니다.

따라서 위의 경우에는 다음과 같습니다.

// 자동 생성 클래스

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

partial void OtherCode();

// 기본 생성자를 재정의하기 위해 수동으로 작성된 클래스

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

다소 제한적 이며이 특별한 경우에는 변경해야 할 파일이있는 경우 올바른 솔루션이 아닐 수도 있지만 부분 클래스에서 기능을 무시하려는 시도를 우연히 발견 한 다른 사람들에게는 이것이 가능합니다. 꽤 도움이됩니다.

OP가 가지고있는 문제는 웹 참조 프록시가 생성자를 가로 채기 위해 사용할 수있는 부분 메소드를 생성하지 않는다는 것입니다.

나는 같은 문제를 해결했으며, 타겟팅하는 웹 서비스가 지원하지 않기 때문에 WCF로 업그레이드 할 수 없습니다.

자가 생성 코드를 수동으로 수정하고 싶지 않았습니다. 누군가가 코드 생성을 호출하면 평평해질 수 있기 때문입니다.

나는 다른 각도에서 문제를 해결했다. 요청 전에 초기화가 필요하다는 것을 알았습니다. 건설 시간에 실제로 수행 할 필요는 없었으므로 GetWebRequest 메소드를 왜곡했습니다.

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;
}

이것은 자동 생성 된 코드를 해킹하는 것이 포함되지 않기 때문에 좋은 솔루션이며, SoAphttPclientProtocol Auto Auto Centated Proxy에 대한 초기화 로그인을 수행하는 OP의 정확한 사용 사례에 적합합니다.

당신은 이것을 할 수 없습니다. 나는 당신이 정의를 만들 수있는 부분 방법을 사용하는 것이 좋습니다. 같은 것 :

public partial class MyClass{ 

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

    public partial void OnCreated();
}

나머지는 꽤 자기 설명이어야합니다.

편집하다:

또한이 서비스에 대한 인터페이스를 정의 해야하는 경우 프로그래밍 할 수 있으므로 실제 구현에 대한 참조가 필요하지 않다고 지적하고 싶습니다. 당신이 이것을했다면 당신은 몇 가지 다른 옵션이있을 것입니다.

나는 당신이 이것을 할 수 있다고 생각합니다 포스트 쇼트, 그리고 누군가가 당신을 한 것처럼 보입니다. 생성 된 부분 클래스의 메소드를 원합니다. 이것이 아직 방법을 작성하는 능력으로 쉽게 번역 될 것인지 모르겠습니다. 아직 샷을주지 않았지만 샷의 가치가있는 것 같습니다.

편집하다: 이것은 같은 줄을 따라 있습니다 또한 흥미로워 보입니다.

이것은 제 생각에 언어의 디자인 결함입니다. 그들은 하나의 부분 방법의 여러 구현을 허용했는데, 이는 좋은 솔루션을 제공했을 것입니다. 더 좋은 방법으로 생성자 (메소드)는 객체를 만들 때 동일한 서명을 가진 부분적으로 부분적으로 표시 될 수 있습니다.

가장 간단한 솔루션은 아마도 추가 부분 클래스 당 하나의 부분 '생성자'방법을 추가하는 것입니다.

public partial class MyClass{ 

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

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

부분 클래스가 서로에 대해 불가지론하기를 원한다면 반사를 사용할 수 있습니다.

// 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));
    }

}

그러나 실제로 그들은 부분 수업과 함께 일하기 위해 더 많은 언어 구성을 추가해야합니다.

Visual Studio에서 생성 된 웹 서비스 프록시의 경우 부분 클래스에서 자신의 생성자를 추가 할 수 없습니다 (가능하지만 호출되지는 않습니다). 대신, [ondeserialized] 속성 (또는 [ondeserializing])를 사용하여 웹 프록시 클래스가 인스턴스화되는 지점에서 자신의 코드에 연결할 수 있습니다.

using System.Runtime.Serialization;

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

때로는 액세스 권한이 없거나 기본 생성자를 변경할 수 없습니다. 이러한 이유로 기본 생성자가 메소드를 호출 할 수 없습니다.

이 경우 더미 매개 변수로 다른 생성자를 만들고이 새 생성자를 만들어 ": this ()"을 사용하여 기본 생성자를 호출 할 수 있습니다.

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

이 클래스의 새 인스턴스를 만들 때 다음과 같은 더미 매개 변수를 전달합니다.

SomeClass objSomeClass = new SomeClass(0);

내가 생각할 수있는 것은 없습니다. 내가 생각해 낼 수있는 "가장 좋은"방법은 더미 매개 변수가있는 CTOR를 추가하고 다음을 사용하는 것입니다.

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);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top