Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 用另一个分部类重写分部类的默认构造函数_C#_Web Services_Wsdl_Overriding_Partial Classes - Fatal编程技术网

C# 用另一个分部类重写分部类的默认构造函数

C# 用另一个分部类重写分部类的默认构造函数,c#,web-services,wsdl,overriding,partial-classes,C#,Web Services,Wsdl,Overriding,Partial Classes,我认为这是不可能的,但如果是,那么我需要它:) 我有一个由Visual Studio 2008从wsdl.exe命令行工具自动生成的代理文件 代理输出是分部类。我想覆盖生成的默认构造函数。我宁愿不修改代码,因为它是自动生成的 我尝试创建另一个分部类并重新定义默认构造函数,但这不起作用。然后,我尝试使用覆盖和新关键字,但这不起作用 我知道我可以从分部类继承,但这意味着我必须更改所有源代码以指向新的父类。我宁愿不这样做 有什么想法、解决方法或技巧吗 //Auto-generated class na

我认为这是不可能的,但如果是,那么我需要它:)

我有一个由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...
      }
   }
}

我想不出什么。我能想到的“最佳”方法是添加一个带有伪参数的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);
这是不可能的。 分部类本质上是同一类的一部分;任何方法都不能定义两次或重写,这包括构造函数


您可以在构造函数中调用一个方法,只在另一部分文件中实现它。

您不能这样做。我建议使用分部方法,然后可以为其创建定义。比如:

public partial class MyClass{ 

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

    public partial void OnCreated();
}
其余的应该是不言自明的

编辑:


我还想指出,您应该为这个服务定义一个接口,然后您可以对其进行编程,这样您就不必引用实际的实现。如果你这样做了,那么你还有一些其他的选择。

我想你也许可以用它来做这件事,看起来有人做了你所做的。我不知道这是否能很容易地转化为编写一个方法并让它的主体替换构造函数的能力,因为我还没有给它一次机会,但它似乎值得一试


编辑:而且看起来也很有趣。

我有一个类似的prolem,生成的代码由一个dbml文件创建(我使用Linq to SQL类)

在生成的类中,它在构造函数末尾调用名为onCreate()的部分void

长话短说,如果您想保留生成的类为您所做的重要构造函数(您可能应该这样做),那么在您的分部类中创建以下内容:

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
        }
    }
}
嗯,, 我认为一个优雅的解决方案是:

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
        }
    }
}
这种方法有一些缺点(如所有问题):

  • 在AutogenCls类的整个构造过程中,MyCustomization内部类的构造函数将在何时执行还不清楚

  • 如果需要为MyCustomization类实现IDiposable接口以正确处理MyCustomization类的非托管资源的处置,我不知道(目前)如何在不接触AutogenCls.cs文件的情况下触发MyCustomization.Dispose()方法。。。(但正如我所说的“还没有”:

  • 但这种方法与自动生成的代码有很大的区别——整个定制在不同的src代码文件中是分开的


    享受:)

    我认为这是语言中的一个设计缺陷。他们应该允许一个分部方法的多个实现,这将提供一个很好的解决方案。 以一种更好的方式,构造函数(也是一种方法)也可以简单地标记为partial,并且在创建对象时,将运行具有相同签名的多个构造函数

    最简单的解决方案可能是为每个额外的分部类添加一个分部“构造函数”方法:

    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生成的Web服务代理,您不能在分部类中添加自己的构造函数(当然可以,但不会调用它)。相反,您可以使用[OnDeserialized]属性(或[OnDeserialized])在web代理类实例化的点上钩住自己的代码

    using System.Runtime.Serialization;
    
    partial class MyWebService
    {
         [OnDeserialized]
         public void OnDeserialized(StreamingContext context)
         {
             // your code here
         }
    }
    

    实际上,现在这是可能的,因为已经添加了部分方法。这是文件:

    基本上,您可以在定义分部类的一个文件中声明和调用方法,但不能在该文件中实际定义方法。在另一个文件中,您可以定义该方法。如果在未定义方法的情况下构建程序集,则ORM将删除对该函数的所有调用

    因此,在上述情况下,它将如下所示:

    SomeClass objSomeClass = new SomeClass(0);
    
    //自动生成类

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

    它有一定的局限性,在这种特殊情况下,如果您有一个生成的文件需要修改,那么它可能不是正确的解决方案,但对于那些偶然发现这一点的人来说,他们试图覆盖部分类中的功能,这可能非常有用。

    有时您没有访问权限,或者不允许更改默认构造函数,因此您无法使用默认构造函数调用任何方法

    在这种情况下,您可以使用伪参数创建另一个构造函数,并使用“:this()”使此新构造函数调用默认构造函数

    当您创建此类的新实例时,只需传递如下伪参数:

    SomeClass objSomeClass = new SomeClass(0);
    

    OP遇到的问题是web引用代理不生成任何可用于拦截构造函数的分部方法

    我遇到了同样的问题,我不能升级到WCF,因为我所针对的web服务不支持它

    我不想手动修改自动生成的代码,因为如果有人调用代码生成,它将变得平坦

    我从另一个角度解决了这个问题。我知道我的初始化需要在请求之前完成,它实际上不需要在c上完成
        public partial class Library {
            List<Book> Books { get; set; }
            partial void InitializePartial() {
                Books = new List<Book>();
            }
        }
    
        public class Book {
            public string Title { get; set; }
        }