0

Say I have a class MyObj with a property Amount.

Can I create an extension method that will be called like this:

myObj.Amount.DoSomething();

Inside DoSomething() I need to be able to get both the property name, which is Amount, and its actual value.

Is this possible?

T.S.
  • 18,195
  • 11
  • 58
  • 78
Franky
  • 1,262
  • 2
  • 16
  • 31
  • 2
    Does this answer your question? [Get names of the params passed to a C# method](https://stackoverflow.com/a/73890720/6196568) – shingo Jan 06 '23 at 04:43
  • @shingo - Thank you for that. I've rewritten my answer to use that voodoo code in the link. – Enigmativity Jan 06 '23 at 06:57

2 Answers2

1

It turns out that there is a way to do it using the [CallerArgumentExpression("value")] attribute

Here's an example of the code you're saying you need:

void Main()
{
    var myObj = new MyObj() { Amount = 42 };
    myObj.Amount.DoSomething();
}

public class MyObj
{
    public decimal Amount { get; init; }
}

public static class Extensions
{
    public static void DoSomething(this decimal value, [CallerArgumentExpression("value")] string caller = "?")
    {
        Console.WriteLine($"caller: {caller}");
        Console.WriteLine($"value: {value}");
    }
}

When run this gives:

caller: myObj.Amount
value: 42

You need to parse out the Amount string.

Unfortunately, this code can easily become difficult to work with and it can be abused.

Look at this extension to MyObj:

public class MyObj
{
    public decimal Amount { get; init; }
    public decimal Amount2() => this.Amount;
    public decimal Amount3(decimal factor) => this.Amount * factor;
}

Now I can write this code:

var myObj = new MyObj() { Amount = 42 };
myObj.Amount.DoSomething();
myObj.Amount2().DoSomething();
myObj.Amount3(2).DoSomething();
decimal x = 43;
x.DoSomething();
44m.DoSomething();
myObj.Amount3(x).DoSomething();
0m.DoSomething("Ha ha");

That gives me:

caller: myObj.Amount
value: 42
caller: myObj.Amount2()
value: 42
caller: myObj.Amount3(2)
value: 84
caller: x
value: 43
caller: 44m
value: 44
caller: myObj.Amount3(x)
value: 1806
caller: Ha ha
value: 0

You will really need to be prepared to parse the various structures returned and you will need to know when your code is calling the extension method and you'll need to know when nefarious calling code is trying to spoof who it is.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
-2

Yes of course, it looks like you want to add an inner class to your class.

class Test
{
    void Main()
    {
        MyObj obj = new MyObj();
        obj.Amount.DoSomething();
    }
}

class MyObj
{
    public Amount Amount;
}

class Amount
{
    public void DoSomething()
    {

    }
}

As far as I know, you cannot string along a function like you showed but you can also add a Func<> as a variable.

As for returning a string and int, there are multiple ways to do that: you can return a JSON string, a Tuple or just create your own class to return.

Display name
  • 413
  • 3
  • 14
  • What does "string along a function like you showed" mean? – Enigmativity Jan 06 '23 at 05:23
  • "you cannot string along a function like you showed" refers to Franky's post of `myObj.Amount.DoSomething()` where he refers to `DoSomething()` as an extension method to `Amount` – Display name Jan 06 '23 at 05:27
  • As you are not Franky, you have no right to claim what he does or does not wish to return. However, I inferred this want from the sentence "Inside DoSomething() I need to be able to get both the property name, which is Amount, and its actual value." where Franky mentioned he wishes to return the property name and actual value. – Display name Jan 06 '23 at 05:29