4

I want to change a function behavior depending how we call the function.

Example:

class A {
    public B instance;
    public void HWorld(){
        Console.WriteLine("Hello from A! \n");
    }
}

class B { // No modification allowed.
    public void HWorld(){
        Console.WriteLine("Hello from B! \n");
    }
} 

static void Main()
{
    B b= new B();
    A a= new A();
    a.instance = b;
    b.HWorld(); // PRINT Hello from B!
    a.instance.HWorld(); //PRINT Hello from A!
}

So my question is: Is there a way (with Event Handler maybe?) to redirect the call B Hworld() to A Hworld() when called as an instance of a specific class?


Other information: I know *it's an XY probleme *: there is a better way to design what I want to do. But I still want to know if it's possible, and how to do it (I don't mind if it require destroying c# compiler).

This is a minimal example: As it doesn't represent the reality, and it's more a theorical question, please avoid: "You can call a.HWorld()".


EDIT

(after on hold) The question I asked was clear. It was an XY probleme, but I was asking for this X question and the topic was closed for Y being unclear (of course, it was not my question). I don't want to debate anymore if there is other way to go around. I'll do an other post for question Y.

MrHeliose
  • 129
  • 8
  • 2
    You can't, since `HWorld` is being called on an instance of class `B` directly. Can you give a more detailed example as to what you want to do so we can help by giving suggestions – MindSwipe Nov 22 '19 at 14:28
  • @MindSwipe I don't know if i should edit to add that, but here is the context: I want to create a library, where I have quite disgusting function (some MultiThreaded generic function using Reflection), so there is a lot of parameters that are stupid (eg: passing the function you want to call as a string). It result in a non-trivial library that will stay unused. So my idea was to hide these function using a "redirection" of function X to function Y. – MrHeliose Nov 22 '19 at 14:37
  • Could you use `A b= new A();` (i.e. use `A` as a wrapper for `B`) – dkasipovic Nov 22 '19 at 14:41
  • 1
    You want a wrapper class. Something that makes the API of class B friendlier and easier to use – MindSwipe Nov 22 '19 at 14:42
  • 1
    Or maybe you actually want A to inherit from B and _override_ the functionality of the method. It's a bit unclear - I'm unsure if you've simplified it to the point where it doesn't appear to provide any benefit. Why _can't_ you call A.Hworld() directly, for instance? That isn't clear at all. It might help us to understand the real scenario. If you can call a.instance.Hworld, then why not a.Hworld()? Or what about if HWorld() accepts parameters which would affect its behaviour? Then perhaps you'd have a wrapper method in A which would call b.HWorld() with specific parameters pre-set... – ADyson Nov 22 '19 at 14:45
  • ...I don't know. We don't know enough about what you're trying to achieve (or more specifically _why_) to give any definitive advice. So yes, potentially it is an X-Y problem, or at least it looks that way right now. – ADyson Nov 22 '19 at 14:47
  • You are unable to modify B, und it's forbidden to call methods from A ? That's really artificial restriction. There must be a reason why to use B - if it does not do, what you want. You want a call to B, not to end up in B. So the result is: Don't Call B. – Holger Nov 22 '19 at 14:49
  • P.S. as for the specific question _Is there a way ... to redirect the call ..._ ...short answer, no, the method being called is unaware of its calling context. And it wouldn't be good if it did. A method should effectively be standalone (apart from any state variables existing within the class where it's declared). If the method starts to depend on the context where it's called then you end up with 2-way dependency relationships, which causes all sorts of problems, and reduces re-usability etc. That's an anti-pattern in object-oriented programming. – ADyson Nov 22 '19 at 14:50
  • @DamirKasipovic no (or maybe i don't understand where you want to go?), a.instance and b need to refere to the same object. – MrHeliose Nov 22 '19 at 14:51
  • @MindSwipe Yes that's it, but I can't make (i think) a good wrapper using a third class, that's why I want to do this kind of things. – MrHeliose Nov 22 '19 at 14:51
  • @MrHeliose well you asked if `b.HWorld();` can return anything other than `HWorld()` from `B`. For that to work, variable `b` needs to point to something other than the `B` class itself. So, create a class `BWrapper` and use it instead of `B`? – dkasipovic Nov 22 '19 at 14:52
  • @ADyson I have think about it, but B is generic type in my code... – MrHeliose Nov 22 '19 at 14:52
  • 2
    "B is generic type in my code"...it's unclear what you mean by this or what the implications are. "generic" has a specific meaning in C#, but it doesn't appear that you mean it in that way here. Therefore it's unclear what you _do_ mean. – ADyson Nov 22 '19 at 14:53
  • @Holger I'm doing a library, I can't modify B as it's not my class. For a call from A, I don't want to do it (read other comment) – MrHeliose Nov 22 '19 at 14:54
  • @ADyson I was meaning generic, look at Edit. – MrHeliose Nov 22 '19 at 15:17
  • @DocBrown I can't write A (i think editor think it's HTML...) Can someone edit if he know how to do it ? – MrHeliose Nov 22 '19 at 15:20
  • 1
    Yes, you always say you cannot modify B, and you don't want to call B. If I cannot buy apples and I don't want to make an apple-pie, I have no problem. If you decide outside B, whether to call it or something else, where's the problem ? There is no "call from A" in your code. The only call is in Main, and you say you want to get rid of that call. But you want to avoid the answer "call A instead of B" also. So everything is prohibited. Hard to understand what degrees of freedom you have, what you are allowed to do at all. – Holger Nov 22 '19 at 15:27
  • 1
    Does `T` implement an interface? How do you know it contains the method `HWorld`? – Derrick Moeller Nov 22 '19 at 15:29
  • 1
    _"I could call A function but because a library need to keep simple, I don't want it"_...this is a completely arbitrary reason. If that's what you need to do in order to achieve the goal, then that's what you need to do. "I don't want to" isn't a reason, if that's the only solution. The point about the definition of T is also a very valid one, above. It muddies the water yet again. – ADyson Nov 22 '19 at 15:34
  • @Holger That's why i asked for this specific solution: I have a lots of constraints. The idea behind this: If I was in C i would have pointers. (And probably there is in the c# background) As accessing memory is catchable (but not trivial) you can trigger an event. – MrHeliose Nov 22 '19 at 15:35
  • I wanted to encourage you to tell what is allowed, and not always what is forbidden. We are not even sure, what you want to achieve, not what you are allowed to do. The idea of modifying the Assembly-Code of a function (which might be possible), makes only sense, if you cannot modify the Call to B, nor B itself. In other words, you really want to hack into a running program or library and you want to modify internal calls. A place you cannot modify at compile-time, is calling a place you cannot modify at compile-time. Right ? – Holger Nov 22 '19 at 15:43
  • @DerrickMoeller T implement a Class. I don't know if it contains a method HWorld, I use reflection to do this, as I said: It was just a minimal exemple. As it's a kind of XY problems (I didn't want to speak so directly about Y and X was also a good question even if it's not the best soution for Y), I'll post a new question probably tomorow about the design to use here. – MrHeliose Nov 22 '19 at 15:43
  • How can I ask to reopen the topic? I've edited to focus on the main question. If it's not possible, I'll do a new post with the same question. – MrHeliose Nov 22 '19 at 18:40

1 Answers1

-1

If the method is also marked virtual, you can make a new class that inherits from B, overrides the method, and get the behavior you want.

If it's not marked virtual, you will not be able to do this.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • Maybe you didn't see my edit but B is generic. I can't do [inheritance](https://stackoverflow.com/questions/748706/generic-inheritance-in-c) – MrHeliose Nov 22 '19 at 15:25
  • 2
    I saw an incomplete edit. If you want to show a generic type, update the code for the type, too, or you still leave us with uncertainty. But nothing about generic types prevents inheritance – Joel Coehoorn Nov 22 '19 at 15:28
  • Can you look at my link about generic inheritance? If you have a solution to answer this question, you solved my prob here! – MrHeliose Nov 22 '19 at 15:45
  • 1
    `B.HWorld` is supposed to be not virtual and cannot be changed, that is the whole point of the question, otherwise it would be trivial. I am pretty sure the OP knows this. – Doc Brown Nov 22 '19 at 15:54