在调用子属性时调用父属性C#

时间:2014-01-31 17:11:48

标签: c# inheritance

我想知道是否有人在调用子属性方法时,它也会调用父属性。 请注意,子代是由edmx的代码生成器生成的。因此,除了为子类添加部分类之外,我无法更改任何内容。 (改变发电机可能太麻烦了。)

我遇到的情况: 我有一个“MyClass”类,它是从数据库自动生成的。除了添加部分类或更改代码生成器之外,我无法对其进行任何更改。

现在,每当调用属性Name时,我都需要“做某事”。我正在考虑是否可以将父母放在那里,并在调用子属性“名称”时让父母调用父母做“某事”。

我想要的是什么:

public class ClassBase
{
    public string Name 
    { 
        get 
        { 
            CallMethod();
            return Name;
        }
    }
}

public class MyClass : ClassBase 
{
    public string Name { get; set; }
}


MyClass myClass = new MyClass();
myClass.Name; < -- this will call the parent as well.

无论如何都要这样做?

提前致谢

4 个答案:

答案 0 :(得分:1)

并不是真正相关,但由于您没有在ClassBase中严格使用自动属性,因此应为Name创建一个私有字符串变量。类似于_name或内部编码标准所规定的内容。

public class ClassBase
{
  private string _name;
  public virtual string Name 
  { 
    get 
    { 
      CallMethod();
      return _name;
    }
    set
    {
      _name = value;
    }
  }
}


public class MyClass : ClassBase 
{
  //Pretty pointless really since you're not doing anything with MyClass.Name.
  public new string Name
  {
    get
    {
      return base.Name;
    }
    set
    {
      base.Name = value;
    }
}


MyClass myClass = new MyClass();
myClass.Name; <-- this will call the parent as well.

答案 1 :(得分:0)

基于“无法更改基类”注释,你可以做很多事情来使代码在基类之前/之后/之后执行,因为当你的新类使用时你的属性/方法不会被调用作为基类(参见详细部分中的示例)。

潜在的解决方案:如果你需要扩展专门设计的parital类,并且它提供了像CallMethod这样的扩展poinst标记为partial - 它应该用于实现类的部分实现它:

partial public class ClassBase
{
    partial void CallMethod();
    public string Name {get {CallMethod(); return "";}}
}


// in generated portion of "ClassBase"
partial public class ClassBase
{
    partial void CallMethod() { /* do something here */ }
}

回答以确切地说“如何调用基类属性”是使用base,但是以这种方式隐藏属性/方法会让人感到困惑(见下文):

new public string Name { get { return base.Name;} }

请注意,您不能在派生类的情况下使用自动属性,因为您明确需要执行一些其他代码。如果在派生类中需要set,则需要自己的支持字段,如:

private string derivedName;
new public string Name { 
   get { return base.Name + derivedName;} 
   set { derivedName = value;}
}

<强>详细信息:

正如在评论中所说,隐藏基类的属性/方法会导致非常混乱的行为。对于你的情况(稍微更新的基类与烘焙领域作为原始样本具有无限递归):

public class ClassBase
{
    private string name;
    public string Name 
    { 
        get 
        { 
            CallMethod();
            return name;
        }
    }
}

您可以尝试在派生类中隐藏Name属性:

public class MyClass : ClassBase 
{
    // notice "new" to show comiler you know what you doing
    // otherwise you'll get warning (but behavior will be the same)
    new public string Name { get; set; }
}

隐藏的问题是基类的方法仍然很容易调用,如果使用派生类作为基类,可能会被错误地调用:

MyClass myDerved = new MyClass();
ClassBase myDervedAsBase = myDerved;
var name = myDerived.Name; // calls MyClass.Name
var name = myDerivedAsBase.Name; // calls ClassBase.Name

这可以通过创建基类'method / property virtual来解决 - 但它需要在基类中进行更改:

public class ClassBase
{
    virtual public string Name { get {... } }
}

public class MyClass : ClassBase 
{
    override public string Name { get { ... } }
}

如果需要从派生类调用基类的方法/属性,请使用base.MethodName(),如:

    override public string Name { get 
      {
          // do some new stuff here
          var baseName = base.Name;
          // maybe even change result
          return baseName;
      }
    }

如果您希望大多数派生类需要这样的行为,那么明确设计基类以强制执行此类行为可能会更好。例如,您可以在计算要返回的值之前/之后调用虚方法的属性,如:

public class ClassBase
{
    virtual protected string AboutToReturnName(string result) 
    {
       return name;    
    }
    public string Name 
    { 
      get 
      {
        var result = "MyName";
        return AboutToReturnName(result);
      }
    }
}

更多想法:

  • virtual的替代方法是partial方法,而不是派生类的方法是从ASP.Net页面等许多“部分”部分组合而成的 - 请参阅Partial Classes and Methods
  • 如果您需要有关更改财产的通知 - 请考虑实施INotifyPropertyChange
  • 如果您需要知道何时调用属性/方法 - 请考虑使用接口并自动生成具有前/后回调的包装类。即模拟框架(如EasyMoq或RhinoMock)和DI容器(如Unity)提供并使用此类功能。

答案 2 :(得分:0)

如果不修改代码生成器,则无法执行此操作。修改必须生成一个呼叫base.Name

答案 3 :(得分:-1)

您可以使用new运算符覆盖子类中的属性。

public class MyClass : ClassBase 
{
    public new string Name { get; set; }
}