Override Default Constructor of Partial Class with Another Partial Class

前端 未结 12 1811
时光取名叫无心
时光取名叫无心 2020-12-28 12:59

I don\'t think this is possible, but if is then I need it :)

I have a auto-generated proxy file from the wsdl.exe command line tool by Visual Studio 2008.

Th

相关标签:
12条回答
  • 2020-12-28 13:23

    This is in my opinion a design flaw in the language. They should have allowed multiple implementations of one partial method, that would have provided a nice solution. In an even nicer way the constructor (also a method) can then also be simply be marked partial and multiple constructors with the same signature would run when creating an object.

    The most simple solution is probably to add one partial 'constructor' method per extra partial class:

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

    If you want the partial classes to be agnostic about each other, you can use reflection:

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

    But really they should just add some more language constructs to work with partial classes.

    0 讨论(0)
  • 2020-12-28 13:24

    The problem that the OP has got is that the web reference proxy doesn't generate any partial methods that you can use to intercept the constructor.

    I ran into the same problem, and I can't just upgrade to WCF because the web service that I'm targetting doesn't support it.

    I didn't want to manually amend the autogenerated code because it'll get flattened if anyone ever invokes the code generation.

    I tackled the problem from a different angle. I knew my initialization needed doing before a request, it didn't really need to be done at construction time, so I just overrode the GetWebRequest method like 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;
    }
    

    This is a nice solution because it doesn't involve hacking the auto generated code, and it fits the OP's exact use case of performing initialization login for a SoapHttpClientProtocol auto generated proxy.

    0 讨论(0)
  • 2020-12-28 13:28

    You can't do this. I suggest using a partial method which you can then create a definition for. Something like:

    public partial class MyClass{ 
    
        public MyClass(){  
            ... normal construction goes here ...
            AfterCreated(); 
        }
    
        public partial void OnCreated();
    }
    

    The rest should be pretty self explanatory.

    EDIT:

    I would also like to point out that you should be defining an interface for this service, which you can then program to, so you don't have to have references to the actual implementation. If you did this then you'd have a few other options.

    0 讨论(0)
  • 2020-12-28 13:30

    Actually, this is now possible, now that partial methods have been added. Here's the doc:

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

    Basically, the idea is that you can declare and call a method in one file where you are defining the partial class, but not actually define the method in that file. In the other file, you can then define the method. If you are building an assembly where the method is not defined, then the ORM will remove all calls to the function.

    So in the case above it would look like this:

    //Auto-generated class

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

    //Manually created class in order to override the default constructor

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

    It is somewhat limited, and in this particular case, where you have a generated file that you'd need to alter, it might not be the right solution, but for others who stumbled on this trying to override functionality in partial classes, this can be quite helpful.

    0 讨论(0)
  • 2020-12-28 13:32

    I had a similar prolem, with my generated code being created by a dbml file (I'm usng Linq-to-SQL classes).

    In the generated class it calls a partial void called OnCreated() at the end of the constructor.

    Long story short, if you want to keep the important constructor stuff the generated class does for you (which you probably should do), then in your partial class create the following:

    partial void OnCreated()
    {
        // Do the extra stuff here;
    }
    
    0 讨论(0)
  • 2020-12-28 13:33

    Nothing that I can think of. The "best" way I can come up with is to add a ctor with a dummy parameter and use that:

    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);
    
    0 讨论(0)
提交回复
热议问题