1

I have a project which uses Autofac to instantiate the objects

builder.RegisterType<AbcWebWorkContext>().As<IWorkContext>().InstancePerHttpRequest();

This AbcWebWorkContext is a subclass of WebWorkContext:

public partial class AbcWebWorkContext : WebWorkContext

In my AbcWebWorkContext I would like to hide a method and a property from the parent class

protected new Customer GetCurrentCustomer(){ //do stuff }
new public Customer CurrentCustomer { //do studd }

But when someone calls

_workContext.CurrentCustomer

The base class property is called. If I call it like this

((AbcWebWorkContext) _workContext).CurrentCustomer

it works.

I would like to know why I am not able to hide the parent method. I can't change the called class because it is in NopCommerce's core, which I would not like to change.

Why is it not hiding the method?

Base class declaration of the methods:

protected Customer GetCurrentCustomer() { // do stuff }
public Customer CurrentCustomer{ // do stuff }

calling GetType() on _workcontext will output

{Name = "AbcWebWorkContext" FullName = "Nop.Web.Framework.AbcWebWorkContext"}

The type hierarchy is IWorkContext (interface) « WebWorkContext « AbcWebWorkContext

_workContext is declared as IWorkContext and Autofac generates an instance as AbcWebWorkContext (as shown above)

p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
JSBach
  • 4,679
  • 8
  • 51
  • 98

2 Answers2

3

The new keyword means that the subclass's method hides the baseclass's CurrentCustomer instead of overriding, so WebWorkContext.CurrentCustomer is a completely different method than AbcWebWorkContext.CurrentCustomer.

You must declare the base class's method as

virtual Customer CurrentCustomer { ... }

And the subclass's method

override Customer CurrentCustomer { ... }

I suggest you read more about polymorphism in c#.

If the methods you're using are actually defined in an interface, IWebWorkContext, you simply encapsulate the base class rather than inheriting from it, like this:

class AbcWebWorkContext : IWebWorkContext
{
    private WebWorkerContext _inner = new WebWorkerContext();

    public Customer CurrentCustomer { ... }
}

If you can't make the base class's method virtual, you have to do something much less elegant, like reflection:

var prop = _workContext.GetType().GetProperty("CurrentCustomer");
var value = (Customer)prop.GetValue(_workContext, new object[0]);
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • I can't because I can't change the core source code. calling gettype() in _workcontext will output {Name = "AbcWebWorkContext" FullName = "Nop.Web.Framework.AbcWebWorkContext"}. So AbcWebWorkContext version of the method should be called. right? – JSBach Mar 14 '13 at 02:42
  • Sorry, I do not own neither the caller code nor the callee code. I am trying to intercept the call to make changes to its behavior without changing the core's code. – JSBach Mar 14 '13 at 03:11
  • @Oscar Then I'm afraid re-implementing the interface is probably your only option. – p.s.w.g Mar 14 '13 at 03:13
  • =/ that is bad. I will ask directly in nopcommerce's forum to check if there is any other point in the system that I could plugin the piece of code I want. Thanks :) – JSBach Mar 14 '13 at 03:31
  • Marking as answer due to the help to get to a conclusion that it is not possible to do what I would like to accomplish the way I want to – JSBach Mar 14 '13 at 03:33
2

I'm not sure if I got your questions right, but I think you need to add a virtual modifier to the method in base class and add a override modifier to method in the subclass.

Find out more on MSDN

Terry
  • 299
  • 1
  • 5
  • 12
  • Yes, that would be overriding the method, but I can't add "virtual" because I cant change the source code – JSBach Mar 14 '13 at 02:39
  • @Oscar, C# is not like Java, methods are not virtual by default. If you cannot modify the base class to make the method virtual, you cannot override it in the child class. You have the option of *hiding* it, but as you have found, it's not that useful except via the derived class' own reference. – Anthony Pegram Mar 14 '13 at 02:42
  • Yes, my bad. I wrote "override" in the title of this question. I meant hide. I will edit it. calling gettype() in _workcontext will output {Name = "AbcWebWorkContext" FullName = "Nop.Web.Framework.AbcWebWorkContext"}. So AbcWebWorkContext version of the method should be called. right? – JSBach Mar 14 '13 at 02:45
  • @Oscar note it *is* actually hiding the base class method. This is how hidden methods are supposed to work. – p.s.w.g Mar 14 '13 at 02:47
  • @p.s.w.g sorry, I didn't get. If it is hiding the base class method, why would the base class method be called instead of the child class? – JSBach Mar 14 '13 at 02:48
  • @Oscar I guess that's because your `_workContext` is declared as a base class instance – Terry Mar 14 '13 at 02:51
  • @Oscar it's hiding the base class's method when calling `AbcWebWorkContext.CurrentCustomer`, the base class's method still exist and is publicly accessible as `WebWorkContext.CurrentCustomer`. So in essence it subclass has two methods, and one is just "hidden". – p.s.w.g Mar 14 '13 at 02:51
  • @Terry not, it is not, I've updated the question. It is declared as IWorkCotext – JSBach Mar 14 '13 at 02:54
  • @p.s.w.g yes, sorry I didn't mentioned it before, is it declared as IWorkContext. Please check the update I just made in the question – JSBach Mar 14 '13 at 02:55
  • @Oscar That does give you some more options. Please see my updated answer for information on encapsulating the base class. – p.s.w.g Mar 14 '13 at 03:02