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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/247800/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 19:46:26  来源:igfitidea点击:

Override Default Constructor of Partial Class with Another Partial Class

c#web-serviceswsdloverridingpartial-classes

提问by Elijah Manor

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.

我有一个来自 Visual Studio 2008 的 wsdl.exe 命令行工具自动生成的代理文件。

The proxy output is partial classes. I want to override the default constructor that is generated. I would rather not modify the code since it is auto-generated.

代理输出是部分类。我想覆盖生成的默认构造函数。我宁愿不修改代码,因为它是自动生成的。

I tried making another partial class and redefining the default constructor, but that doesn't work. I then tried using the override and new keywords, but that doesn't work.

我尝试创建另一个部分类并重新定义默认构造函数,但这不起作用。然后我尝试使用 override 和 new 关键字,但这不起作用。

I know I could inherit from the partial class, but that would mean I'd have to change all of our source code to point to the new parent class. I would rather not have to do this.

我知道我可以从部分类继承,但这意味着我必须更改我们所有的源代码以指向新的父类。我宁愿不必这样做。

Any ideas, work arounds, or 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...
      }
   }
}

采纳答案by configurator

This is not possible. Partial classes are essentially parts of the same class; no method can be defined twice or overridden, and that includes the constructor.

这不可能。部分类本质上是同一类的一部分;任何方法都不能被定义两次或被覆盖,包括构造函数。

You could call a method in the constructor, and only implement it in the other part file.

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

回答by James Curran

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:

没有什么我能想到的。我能想到的“最佳”方法是添加一个带有虚拟参数的 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);

回答by jonnii

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.

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

回答by cfeduke

I am thinking you might be able to do this with PostSharp, and it looks like someone has done just what you want for methods in generated partial classes. I don't know if this will readily translate to the ability to write a method and have its body replace the constructor as I haven't given it a shot yet but it seems worth a shot.

我想你也许可以用PostSharp做到这一点,而且看起来有人已经为生成的部分类中的方法做了你想要的。我不知道这是否会很容易转化为编写方法并使其主体替换构造函数的能力,因为我还没有尝试过,但似乎值得一试。

Edit: this is along the same linesand also looks interesting.

编辑:这是沿着相同的路线,看起来也很有趣。

回答by Tom Chantler

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

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

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

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

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

回答by Tom Chantler

Hmmm, I think one elegant solution would be the following:

嗯,我认为一种优雅的解决方案如下:

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

This approach has some drawbacks (as everything):

这种方法有一些缺点(就像一切一样):

  1. It is not clear when exactly will be executed the constructor of the MyCustomization inner class during whole construction procedure of the AutogenCls class.

  2. If there will be necessary to implement IDiposable interface for the MyCustomization class to correctly handle disposing of unmanaged resources of the MyCustomization class, I don't know (yet) how to trigger the MyCustomization.Dispose() method without touching the AutogenCls.cs file ... (but as I told 'yet' :)

  1. 在 AutogenCls 类的整个构建过程中,MyCustomization 内部类的构造函数究竟何时执行尚不清楚。

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

But this approach offers great separation from auto-generated code - whole customization is separated in different src code file.

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

enjoy :)

请享用 :)

回答by nreyntje

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.

但实际上,他们应该添加一些更多的语言结构来处理部分类。

回答by Edward

For a Web service proxy generated by Visual Studio, you cannot add your own constructor in the partial class (well you can, but it does not get called). Instead, you can use the [OnDeserialized] attribute (or [OnDeserializing]) to hook in your own code at the point where the web proxy class is instantiated.

对于 Visual Studio 生成的 Web 服务代理,您不能在分部类中添加自己的构造函数(当然可以,但不会被调用)。相反,您可以使用 [OnDeserialized] 属性(或 [OnDeserializing])在 Web 代理类实例化的位置挂接您自己的代码。

using System.Runtime.Serialization;

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

回答by rrreee

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

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.

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

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.

它有些限制,在这种特殊情况下,如果您有一个需要更改的生成文件,它可能不是正确的解决方案,但对于其他人偶然发现此尝试覆盖部分类中的功能,这可以很有帮助。

回答by Shadi

Sometimes you don't have access or it's not allowed to change the default constructor, for this reason you cannot have the default constructor to call any methods.

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

In this case you can create another constructor with a dummy parameter, and make this new constructor to call the default constructor using ": this()"

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

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

And when you create a new instance of this class you just pass dummy parameter like this:

当您创建此类的新实例时,您只需像这样传递虚拟参数:

SomeClass objSomeClass = new SomeClass(0);