The C# Feature I Use Instead of Reflection

Поделиться
HTML-код
  • Опубликовано: 16 сен 2024
  • Check out the ABP Framework here: bit.ly/3UmfRbh
    Check out my courses: dometrain.com
    Become a Patreon and get source code access: / nickchapsas
    Hello everybody I'm Nick and in this video I will introduce you to a set of attributes that allow you to get compile-time metadata about your code and use them in runtime. In many cases the data you will collect are impossible to get with something like reflection during runtime.
    This video is sponsored by abp.io.
    Don't forget to comment, like and subscribe :)
    Social Media:
    Follow me on GitHub: bit.ly/ChapsasG...
    Follow me on Twitter: bit.ly/ChapsasT...
    Connect on LinkedIn: bit.ly/ChapsasL...
    Keep coding merch: keepcoding.shop
    #csharp #dotnet

Комментарии • 48

  • @thinker2273
    @thinker2273 Год назад +54

    I think it was mentioned in a recent stream with Mads Torgerson that there is a proposal to add a [CallerMemberInfo] attribute which would work the same as [CallerMemberName], but would allow you to recieve a MemberInfo instead of a string. Personally I think that would make the entire "caller" family complete, and would also act as a more reasonable alternative to the proposed infoof expression.

    • @KieranFoot
      @KieranFoot Год назад +2

      That would be a great addition.

  • @Sanabalis
    @Sanabalis Год назад +27

    I've used all except CallerArgumentExpression. One of the more useful things I did was inject the Caller, File, and Line number into the logger scope at the start of methods, making debugging from logs much easier, especially if you're looking at logs that don't have stack trace.

    • @jptouron3080
      @jptouron3080 Год назад

      hi! do you have a sample on how to do that? was looking for it myself :-)

    • @Sanabalis
      @Sanabalis Год назад +3

      ​@@jptouron3080
      public static class LoggingExtensions
      {
      public static IDisposable? AddCallerScope(this ILogger logger, string memberName = "", string filePath = "",
      long lineNumber = 0, [CallerMemberName] string methodName = "", [CallerLineNumber] long logScopeLineNumber = 0)
      {
      return logger.BeginScope("{callerMember}, {callerPath}:{callerLine} -> {method}:{lineNumber}",
      memberName, filePath, lineNumber, methodName, logScopeLineNumber);
      }
      }
      then simply use like this:
      public void SomeMethod(int methodArgument, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "", [CallerLineNumber] long lineNumber = 0)
      {
      using var logScope = _logger.AddCallerScope(memberName, filePath, lineNumber);
      .........

  • @TheMAZZTer
    @TheMAZZTer Год назад +13

    CallerMemberName is useful if you are making an INotifyPropertyChanged implementation that handles multiple properties. You can have your property setters call a private helper method that has a CallerMemberName and use this to access the property name that was modified easily, so you can add it to the EventArgs.

    • @marsovac
      @marsovac Год назад +1

      Why not simply use an MVVM framework, caliburn prism or whatever and the PropertyChanged nuget. Completely remove them from code and implement them via some form of precompilation on classes that implement INotifyPropertyChanged. INotifyPropertyChanged and much of the WPFish stuff is just boilerplate you don't want to deal with. Use auto properties and if you need to do something override the created methods.

  • @F1nalspace
    @F1nalspace Год назад +2

    I love the caller attributes, i use them whenever i can. But argument expressions was new for me, so thanks for sharing.

  • @aforslow
    @aforslow Год назад +3

    Merry Christmas, Nick! You’re doing awesome work with this channel!

  • @amrosamy8232
    @amrosamy8232 Год назад

    One of the important things is getting the type of the returned value of the expression

  • @splith
    @splith Год назад

    6:16 I was going to call you out on the use of nameof for number, but of course you had it!

  • @davidwilliss5555
    @davidwilliss5555 Год назад +2

    I can see a good use for the last two. Sometimes you cannot attach a debugger (maybe it's running at a customer's location) and to debug where something is happening, you sprinkle a lot of logging in the code. This would allow you to write a static LogDebug message that automatically knows the filename and line of where it's called and include that in the log message.

  • @noldor__
    @noldor__ Год назад

    Thank you for the video. It was very helpful. These features look really handy if you're implementing deeper diagnostic logging for your code. For example, I needed to do this for a shared library I was working on. I needed to log information about what modules and classes called it, as well as the arguments it was called with, so that I could log parameters and results and have an idea about how people were using the library. This way, we could have a statistics report at the end of the day. I had to use a lot of reflection and do a lot of string parsing of the Current StackTrace, but it still wasn't enough. I had to add extra parameters to my methods so developers could pass more information. If these features were available back then, it would have been a lot of use to me.

  • @petrucervac8726
    @petrucervac8726 Год назад +5

    CallerMemberName is used extensively in WPF

    • @krccmsitp2884
      @krccmsitp2884 Год назад +4

      Fits perfectly with INotifyProperyChanged.

  • @craigfranchuk9339
    @craigfranchuk9339 Год назад

    Great video. I’ve been a fan of the caller member attributes for enhancing error log details for some time. I didn’t know about that feature to capture the input arguments. Very cool and thank you for sharing.

  • @dmitrywho7990
    @dmitrywho7990 Год назад +2

    We usually like to enrich logging with custom fields and they way we are doing it with ILogger - I believe these attributes are not as useful because there will be a number of methods in stack trace between ilogger call and actual logging handler

  • @Denmaverick39
    @Denmaverick39 Год назад

    Definitely gonna implement the line number caller in the exception libraries

  • @MichaelBattaglia
    @MichaelBattaglia Год назад +4

    Very fascinating stuff! Question: is there an attribute that can get all of the caller values for all of the arguments when there is more than one without having to individually add a argument for each new one?

    • @rasimismatulin1400
      @rasimismatulin1400 Год назад

      If you will call Example() methods from several another methods, each compilation result will call Example() with it name.
      Test1() => Example("Test1")
      Test2() => Example("Test2")

  • @SherlockHolmesCologne
    @SherlockHolmesCologne Год назад

    This is last example is actually similar to the C++ macro __FILE__ and __LINE__, which can be useful in UTests.

  • @reikooters
    @reikooters Год назад

    I use CallerMemberName, CallerFilePath and CallerLineNumber in a generic logging helper class that I reuse in projects which basically just contains wrappers for the Serilog Information, Warn, Error etc functions, which prepends the file/member/line number at the beginning of the message, so I can see where in the code the log was created from. For the file path, I'm using Path.GetFileNameWithoutExtension() so as to just keep the filename so logs arent cluttered with the full path. I did not know about the new Argument one, it's interesting but not sure when I'd use it.

  • @zsoltszilagyi4768
    @zsoltszilagyi4768 Год назад +1

    These attributes are a great addition but still very situational. For example, they can not work with params constructs, and this really breaks their usage in most logging methods, unless you are using string interpolation in your message.

    • @saylorsedell2380
      @saylorsedell2380 Год назад

      Exactly, which is the problem I'm now running into when setting up Serilog the correct way

  • @Looooooka
    @Looooooka Год назад +3

    Is there an c# IL viewer extension for visual studio(not code)? 😤

    • @krccmsitp2884
      @krccmsitp2884 Год назад +2

      Have a look at "IL Spy 2022"

    • @anreton
      @anreton Год назад +1

      And check ILDasm.

  • @JoeEnos
    @JoeEnos Год назад +1

    I’m curious what happens if you mix and match languages with the argument one - like you call from VB, passing in a lambda to a C# method. I guess that’s something to try later.

  • @fakhrulhilal
    @fakhrulhilal Год назад

    Wonderful, it's more on build time rather than compile time.

  • @TechAndMath
    @TechAndMath Год назад

    Hi,great video. can you do a session on model validation performance in webapi world? Always curious if fluent validation is faster or slower than the default validation attributes?

  • @iOLlVER
    @iOLlVER Год назад

    Would be interesting to get the CallerArgumentExpression as an actual Expression

  • @klocugh12
    @klocugh12 Год назад

    Those could be extremely useful for debugging dlls created at runtime.

  • @ivandrofly
    @ivandrofly Год назад

    Thanks

  • @haxi52
    @haxi52 Год назад

    I use CallerMemberName the most, its really handy for implementing IPropertyChanged.
    CallerFileName and line number can be really useful for error logging.

  • @vm123
    @vm123 Год назад

    Wish the added new keyword pathof(exp) which would do the same job as nameof but returning full path eg. Foo.Bar.PropName instead of just PropName

  • @user-dzimka
    @user-dzimka Год назад

    Hello. Could anybody help me - what is extention are used on 7:10 as IL viewer but with higth level c#?

  • @anonimzwx
    @anonimzwx Год назад

    this works in unity?

  • @moatazal-ali8589
    @moatazal-ali8589 Год назад

    Hi nick thanks a lot for yours courses and videos ... Can you please make a course for mongoDB and dynamic DTO to validate dynamic forms or dynamic JSON

  • @tmhchacham
    @tmhchacham Год назад

    Can you get the class name?

  • @jacobstamm
    @jacobstamm Год назад

    AN’T WORK?

  • @EdKolis
    @EdKolis Год назад +1

    I feel like this feature could be used to exploit vulnerabilities in calling code when implemented in a library. The library uses this feature to find the names of methods in code that calls it, and uses this to seek out exploits by brute force calling those methods using reflection...

    • @EdKolis
      @EdKolis Год назад

      Oh wow, the expression one is even worse. A library could extract all sorts of sensitive data that whoever wrote the calling code thought the library wouldn't have access to because it's being evaluated before being passed in! Yikes!

    • @EdKolis
      @EdKolis Год назад

      e.g. CallLibrary(HashPassword(pword, "secretsalt")); exposes the salt

    • @paulkoopmans4620
      @paulkoopmans4620 Год назад +2

      @@EdKolis putting your salt in... right as a string there... anyone could get that out of your source with reflector, dotPeek, ilDasm. And really... that goes for all of your code. It really is a non-issue at that point.

    • @MaximilienNoal
      @MaximilienNoal Год назад +1

      Unless you put secrets in your version control, This isn't an issue at all.

    • @LeMustache
      @LeMustache Год назад +2

      Installing a malicious nuget package can already do much worse things than getting some potentially hardcoded string.
      Like hell, even the dumbest thing - it could literally scan the entire executable on runtime and send all the strings it finds to the attacker.
      If you're worried about it the actual issue is that you're using a fishy library in the first place, not the feature.
      It's kind of like worrying that your bathroom lock is too weak to stop a thief. Worry about your front door first.

  • @mysterious_commenter3285
    @mysterious_commenter3285 Год назад

    First

  • @alimorgan1407
    @alimorgan1407 Год назад

    First