部分类的默认构造函数与另一个部分类重写
我不认为这是可能的,但如果是,那么我需要它:)
我有一个由Visual Studio 2008的wsdl.exe命令行工具自动生成的代理文件。
代理输出是部分类。 我想覆盖生成的默认构造函数。 我宁愿不修改代码,因为它是自动生成的。
我试着做另一个部分类,并重新定义默认的构造函数,但这是行不通的。 然后我尝试使用覆盖和新的关键字,但是这是行不通的。
我知道我可以从部分类inheritance,但这意味着我将不得不改变我们的所有源代码指向新的父类。 我宁愿不必这样做。
任何想法,解决办法或黑客?
//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... } } }
这不可能。 部分class级基本上是同一class级的一部分; 没有方法可以被定义两次或重写,并且包括构造函数。
你可以在构造函数中调用一个方法,只在另一个部分文件中实现。
我有一个类似的prolem,我的生成的代码是由一个dbml文件(我是Linq到SQL类)创build的。
在生成的类中,它在构造函数的末尾调用一个名为OnCreated()的部分void。
长话短说,如果你想保留重要的构造函数的东西生成的类为你(你可能应该这样做),然后在你的部分类创build以下内容:
partial void OnCreated() { // Do the extra stuff here; }
嗯,我认为一个优雅的解决scheme是:
//* 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类的整个构build过程中,何时执行MyCustomization内部类的构造函数并不清楚。
-
如果需要为MyCustomization类实现IDiposable接口来正确处理MyCustomization类的非托pipe资源,我还不知道如何触发MyCustomization.Dispose()方法而不触及AutogenCls.cs文件…(但正如我告诉'但':)
但是这种方法与自动生成的代码提供了很大的分离 – 整个定制在不同的src代码文件中是分开的。
请享用 :)
实际上,现在已经有可能,现在已经增加了部分方法。 这里是文档:
http://msdn.microsoft.com/en-us/library/wa80x488.aspx
基本上,这个想法是你可以在你定义分部类的一个文件中声明和调用一个方法,但实际上并没有在那个文件中定义方法。 在另一个文件中,您可以定义该方法。 如果您正在构build方法未定义的程序集,那么ORM将删除对该函数的所有调用。
所以在上面的情况下,它会看起来像这样:
//自动生成的类
namespace MyNamespace { public partial class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol { public MyWebService() { string myString = "auto-generated constructor"; OtherCode(); } } } partial void OtherCode();
//手动创build的类为了覆盖默认的构造函数
partial void OtherCode() { //do whatever extra stuff you wanted. }
这是有限的,在这种特殊情况下,如果你有一个生成的文件,你需要改变,这可能不是正确的解决scheme,但对于其他人偶然尝试覆盖部分类的function,这可以相当有帮助。
你不能这样做。 我build议使用一个部分的方法,然后你可以创build一个定义。 就像是:
public partial class MyClass{ public MyClass(){ ... normal construction goes here ... AfterCreated(); } public partial void OnCreated(); }
其余的应该是非常自我解释。
编辑:
我也想指出,你应该为这个服务定义一个接口,然后你可以编程,所以你不必引用实际的实现。 如果你这样做,那么你会有其他的select。
我想你可以用PostSharp来做到这一点,它看起来像一个人已经做了你想要的生成的部分类中的方法 。 我不知道这是否会很容易转化为编写一个方法的能力,并让它的主体replace构造函数,因为我还没有给它一个镜头,但它似乎值得一试。
编辑: 这是沿着相同的线条 ,也看起来很有趣。
OP得到的问题是Web引用代理不会生成任何可用于截取构造函数的部分方法。
我遇到了同样的问题,我不能只升级到WCF,因为我所瞄准的Web服务不支持它。
我不想手动修改自动生成的代码,因为如果有人调用代码生成,它将变得扁平化。
我从另一个angular度解决了这个问题。 我知道我的初始化需要做一个请求之前,它不需要在施工时间完成,所以我只是像这样覆盖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; }
这是一个很好的解决scheme,因为它不涉及黑客自动生成的代码,它适合OP的SoapHttpClientProtocol自动生成代理执行初始化login的确切用例。
这在我看来是一个语言的devise缺陷。 他们应该允许一个部分方法的多个实现,这将提供一个很好的解决scheme。 以更好的方式,构造函数(也是一种方法)也可以被简单地标记为部分,并且在创build对象时,具有相同签名的多个构造函数将运行。
最简单的解决scheme可能是为每个额外的部分类添加一个部分“构造函数”方法:
public partial class MyClass{ public MyClass(){ ... normal construction goes here ... OnCreated1(); OnCreated2(); ... } public partial void OnCreated1(); public partial void OnCreated2(); }
如果你想让部分类彼此不可知,你可以使用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)); } }
但是他们真的应该只是添加更多的语言结构来处理部分类。
没有什么我能想到的。 我能想出的“最佳”方法是添加一个虚拟参数的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);
对于由Visual Studio生成的Web服务代理,您不能在分部类中添加自己的构造函数(也可以,但不会被调用)。 相反,您可以使用[OnDeserialized]属性(或[OnDeserializing])在Web代理类实例化的位置挂接自己的代码。
using System.Runtime.Serialization; partial class MyWebService { [OnDeserialized] public void OnDeserialized(StreamingContext context) { // your code here } }
有时你没有访问权限,或者不允许修改默认的构造函数,所以你不能有默认的构造函数来调用任何方法。
在这种情况下,你可以创build一个具有伪参数的构造函数,并使这个新构造函数使用“:this()”调用默认的构造函数
public SomeClass(int x) : this() { //Your extra initialization here }
而当你创build这个类的新实例时,你只需要传递这样的伪参数:
SomeClass objSomeClass = new SomeClass(0);