C# Reflection Explained (Claim generation example)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome everyone today we're gonna be covering reflection i've seen a couple of tutorials on youtube about it and don't think they give you the correct mindset to approach it sure they give you some examples and explain sort of what you can do with reflection but they don't really give you that mental switch where you can now take a look at the problem and you can think oh i can actually apply a reflection to this so this is what i'm going to attempt to do in this tutorial hopefully i can give you a little push or change your perspective on how you look at code so you can recognize when to use a reflection to solve a problem okay starting with a really simple example we have a string hello world and we just dump it now what i want you to do first is i want you to forget about strings right and this is no longer a string right this is just a representation of a word this is at the core of it of what i will refer to as just data right it's just some data a character is just some data a number is just some data it's uh how our program works when we receive some data we basically put this structure in c sharp to basically put stuff in a string and then that string is maybe on the class and then we know how to interpret that data or rather c sharp knows then how to interpret that data and how to manipulate that data okay so what we're doing here is we essentially let's say we don't know what a string is even though we define it c-sharp just knows that it's a string so then we try to split it we can still perform the same operations to it even though we haven't actually stored it in the string but i mean it kind of is inferred that it's a string so what am i alluding to uh i want to take this one step further before dropping the bomb so what we're going to do is we're going to now also we're going to still have a string but this string is now going to mean something else and again if per if you can't forget that it's a string it's just a word right it's something we say it's something we can type in a notepad we type it in a notepad when a regular human when i say regular human not a programmer writes something in word document he doesn't think i'm writing strings no he's writing paragraphs words sentences right this is what i want you to imagine that you're doing right now you're just writing letters and they they have some meaning right so we're trying to get rid of this notion of that this means anything okay but for now i'm just gonna give a little json object with a simple property but when you look at this make sure you look at it as a word or maybe a paragraph whatever makes more sense uh so the way we represent this a little bit awkward but we'll do kind of the same so hello world and then let's say we'll just say prop and we can dump this and again we will have the same representation we can kind of do the same kind of manipulations to this word but what what is more interesting is that we can crystallize these words into constructs right so this string right here means something to us humans and it's the it's basically json format right it's json format to represent the data we can also have something along the lines of prop equals hello world and this is what you could see when a form is just being submitted right so there are other ways to represent the same data but json format is just one of them why well it's because then we can use the json serializer library to take this data in its more or less pure form where it's like the json data we can basically send it to anywhere to like a javascript a python api a c-sharp api java api maybe and then the api can then take this json and de-serialize it and then basically the conversion is happening from the data world into the c-sharp world so you basically do the mapping right you basically you have the object in the real world as it is it's pure form it's just strings it's characters right and maybe when it's traveling over the wire it's just zeros and ones you basically take that and you push it into the language and when we push it in the to the language this is what happened right so we have a public class a will have a prop i'll just call it prop as well and i have a little extension method that will essentially do the conversion automatically so i will say convert to and this is link only so you don't have access to this okay i'll say that i want to convert it to a this type and at the end i'm just gonna get eight all right so it's as if i was doing json dc realization it's exactly that so now that we have converted to a class it's an object in a specific form okay so it's no longer json we've l we have lost this a read original meaning for this data it is now in a rep in the form of representation of this class so this class is like a blueprint and it's like a jug light right so only specific things can go in this jug or it's like a hole right you know one of those where you have like a little box and you're trying to put the circle thing in the circle thing and then the square thing and the square thing so it's kind of like that where we basically we take this json and whatever shape it is we try to fit it in this hole and oh look it fits and by the end of it we get a filled object right where it just where the object is just filled with the data from the original string it doesn't matter that the string was json it's just when it does come in json format we are able to transfer it into the class representation right so this one right here so why am i telling all this why why the ramble i thought we know strings and we know words and we know jason well what if i what if i've written something like this so let's say right uh yeah i mean that looks alright don't it a string still data so the takeaway here is that you have data in some format and then you're able to map it to a different form right in our case we're taking json and we're mapping it to the a object now what i've did here is i've literally just rewritten the a object but in a word representation uh what's the difference between this and this well the only real difference is that well one is written not as a string but the the characters are exactly the same and it's inside link so link knows how to compile and analyze c-sharp so it knows how to recognize syntax right and when the c-sharp compiler reads your file which contains text which can which is written in c-sharp format so you're just writing letters in c sharp format so when the compiler takes it it knows how to take your code which is c sharp format and then convert it to il format which then the virtual machine executes okay so again this is not so much relating to reflection or how to use reflection it's trying to change your perspective on that when you're writing code it is just data that you're writing you're producing data it's like when you go on facebook and you make a post you've just produced a piece of data where the content for the post will be the thing that you have written and the author will be the profile that you filled out before here what you have instead of facebook is you have your id you have your text editor and instead of posting to facebook you save to your file system and instead of writing your post what you're doing is you're writing c sharp now comes the time where we have some sort of a data type right so we have data we know how to put it in a data type and we can then manipulate it we also have some data we can morph it to a different type convert it to a different type then we can manipulate it and then in our case when we have written the code and we want to access the data of our code from our code so it's the code being self-aware about the data that it consists from it's self-aware data essentially it can then manipulate itself to produce some interesting things right so the videos in these playlists like middleware dependency injection and we see they're filled with reflection right so how do you arrive at a point where you can say right i am ready to use reflection okay so again just a blanket statement before we dive into the example when you write code you produce data and reflection allows you to manipulate that data inside the code right it's self-aware data what we're going to go into now is a visual studio application and the example is going to be that of authentication where we want to grab every action from a controller that is under under authorization and we want to produce a claim for it so we're going to be able to delegate access to users by authorized action okay so here inside the application before going over it while we still have the memory of the outline i just made if you already forgotten it go watch it again before we dive into it what you're looking at here this project this is data this is the things that you've already written this is your essay right imagine if your essay could do something by being self-aware right what if we can generate a claim for all authorized actions right we already know about all the actions that we have in our controller we know which ones are authorized can we not just write some code that generates the claims based on authorized actions we can that's basically a use case for a reflection it's when you have this data that you've already written and you're ready to use some knowledge about your application within the application right it doesn't have to be a constant usage it can be just a one-time setup which is kind of what we're gonna do today so primarily there's gonna be the two controllers so the manage controller right uh decided to spice it up a little bit we're gonna have the authorizing attribute we're gonna have the yellow anonymous attribute we're gonna basically generate a claim for each one of these and then the home controller we have no authorization on the home controller just an index page and then we have the sign in page so this is where initially we're gonna display the page and there's gonna be a list of claims to pick from and then we're going to sign in so it's not a proper production ready application but nevertheless this is just basically aggregating all the claims that could we that we could possibly want okay and then from the picked claims we're just going to create an identity and if it works right and then there's also this condition where the home controller isn't authorized but we have an authorized action okay so again it's not c sharp code i don't want you to look at this as c sharp code i want you to look at this as data that you have written right it's an essay it's just a collection of words reflection is just a convenient way to manipulate your words okay so uh as that is the goal what we're going to do now is we're going to take a look at what is actually what what this application is right so we have the startup in the startup i have the configuration see that was created from a template i have the authentication regular at cookie authentication i have my own authorization selected so i override the default policy and all i'm saying is i want to add a requirement of auto-generated claim it doesn't matter what this is but this is basically just to trigger this authorization handler if you want to know more about authentication go watch my authentication series i will leave the link annotation somewhere there right and this is where again we are going to do some checking of the claim that we have to the controller that we're going like are we authorized right uh then where we add the auth handler this is where we have the auto generated claim so it's in the auth handler here and yep and then the singleton claims service so because i'm not using a database for simplicity purposes this is just something that's going to be returning claims where we'll stick the code in here once we got it working and then we have add controllers with views right super simple a bunch of stuff here that doesn't matter static files doesn't matter i think i deleted them all except the favicon uh use routing use endpoints author authentication authorization right it's a pretty much a very simple setup for the constants here i just have the web app claim type so it's just a claim type that i'm gonna assign for all the claims that are gonna come from this app okay so when i'm gonna go into the home controller uh when i i'm going to create a new claim i'm gonna get a web claim type and then when i'm gonna go into my off handler that's when i will be able to bring up this claim type as well and just filter by it other than that uh nothing fishy going in my program.cs everything else is good to go right so what i'm gonna do is i'm gonna build the application and what that is going to do is it's going to produce a dll for me right so webapp.dll now what we're going to do is we're going to go into link and in here i will uh actually yeah let's remove this this is not really that important that was more of a talk not sure why i copied that but yeah uh what i'm going to do now is i'm going to browse for this project so let's go here where is my reflection yep there it is bin debug whip and web app dot dll right so i'm bringing in the dll into link pad so it will be a little bit easier to inspect the program okay so once i'm here let's go ahead and grab the startup class right so startup we can go ahead and import import it and here we have it so if we want to construct it we will have to pass an i configurable into it all right yada yada we can make a startup okay so reflection we want to know about reflection right so this is not really the use case the primary reason i brought into the startup is just to know that the library has been added the way that you sort of go traverse into the reflection world is you want to understand the type that you're getting right so we have startup if you have a static type you can do this okay and actually let me bring this back here so type off startup and then we dump it so here is how we traverse into a static type so static type is when you can see highlighted in green you can see this is instantiated so we can't know the type of generics for example so what you could do sometimes is or we don't know the type of objects rather you can take the startup and you can get type like this and you can dump it okay so this is basically traversing into the world of reflection this is now where you're like oh my god i know everything about the startup what it is what it contains what it has okay so this is essentially another thing is just to note off is that a get type what it does is returns you a system.type object i can't hover over it but that's what it gives you back a system.type object so you just get a class back and if we do get type you get information of the runtime type right so this is now information about the object that contains information about types okay so it's kind of again it gets loopy very quickly right it doesn't matter what do we want we want to slowly zoom in on all the actions that we have that have authorization okay uh the the first trick really to do is just let's just get all types from the application right so the way you do this is you just go assembly and get types okay so wherever this type is contained whatever assembly it's contained in so it's going to be that webapp.dll i want to get all types from it all right and we can go ahead and dump this don't forget the semicolon so here we get a bunch of types from disassembly okay so these are all the classes that i have defined uh which ones are gonna contain actions do you think well i think it's the controllers so let's go ahead and do this here we're just to use our good old link to basically say name of the type so if we go into the home controller we can try to find something that says home controller for example like the name and make sure we get the name right if you don't want to name your controllers ending with controllers you can inspect the base type and you can look for base type of controller right so there are ways to tackle this and there's a lot of information on google so don't be scared to google what i'm gonna do is i'm gonna say ends with controller okay so here we are we got our two controllers let's get all the actions right uh so again we're just gonna deselect this is the same as you would have a list of objects and you're just manipulating a regular list of objects this is data about your program all right so any information that you want to know about your code it will be available here okay and even more than you can conceive at this point but nevertheless so the x at this point is going to be the type of controller what we want to do is we want to get all the methods right so we can go ahead and call the get method function and here we are going to get quite a few um yeah so the primary thing is that it's going to be getting methods of the base type so the home controller so the home controller inherits from controller and the controller inherits from controller base and some other interfaces okay so the problem here is that we can see some of these types from the controller from the controller base so we want to eliminate that and usually it doesn't matter how slow your reflection is if it's a one-time setup which it is in this case just make sure you do your setup on startup or put it in a lazy and then cache it so you can reuse it otherwise just be wary that reflection can be slow so don't go ahead and use it everywhere okay so get messages uh let's go ahead and filter this or rather get methods let's go ahead and say that we only want the methods and we'll have to change this let's let's change this to m okay so m for method and we will take the declaring type and because x is a type and x is specifically a type of home controller we will say that the declaring type equals x okay so this is what we want essentially so let's go ahead and dump this and now we'll get an innumerable with four records two enumerables one for each controller and one will be index sign in sign in so this is the home controller and then the other one secure secure secret allowed okay so let's go ahead turn this into one list so we'll change this to select many there we go and it's one list okay so we basically flattened out the list magic right that's undead this a little bit so now what we're after are the actions with specific attributes so if we scroll through this maybe will we see attributes method handle nope right or oh runtime custom attributes yeah that's pretty much it uh on some of them will we see it maybe basically we'll go through this logically rather than trying to look it up first thing that i want is i want to include all the methods which have the authorized attribute so here we'll say where x again x is now going to be method information and for x we can get get custom attribute right and here we can say let's just store the type of the attribute in a variable so author equals type of authorize authorize attribute bring it in right so this is going to be the auth attribute and here i want to say that it has it so it doesn't equal no if we have one then we good so let's go ahead and see which ones we have so it's only one item it's only the one in the home controller and that's because the ones in the manage controller have the authorized attribute on the controller itself okay so that's another thing that i want to include i want to go into x and i want to get the a i want to do or i want to go into declaring type i want to get custom attribute from there so because we know that the declaring type is going to be the controller we want to see if there is an authorized attribute on the controller right so let's do auth attribute and then it doesn't equal no okay so here we are one thing is this allowed function so i have the allow anonymous on it let's go ahead and handle that as well uh let's just put a new where clause because otherwise that one's gonna get nasty and we'll say that get custom attribute uh and let's say a non actor allow anonymous attribute right there all right there and that this equals no okay so we're basically checking that this is no and there we are so home controller has this authorized managed controller is authorized by itself and these are not the one these are the ones that do not have a law anonymous tag so these are all of our authorized actions so there is a couple of things that we want to do here essentially as you can see there is not much difference between secure and managed controller other than the amount of parameters that it takes so we kind of want to amalgamate this information about these actions into some sort of form where we can know what controller it came from what the name of the action is and what parameters it has so we can distinguish between actions that have the same name okay and obviously this is not production perfect yet you can have functions in your controllers they're just helper functions you know obviously handle that yourself what i'm after here is let's put a select and sometimes you can just get some interesting information from to stringing it so from to string it i can see the return type of the function and the parameter types that it takes so i'm not so worried about the return type i'm more worried about the signature so and another thing so i want to get rid of this bit and i want to include the controller so we can dump the x here and we will basically get information about these controllers as well so for example if we take the home controller uh we maybe want to take the namespace as well uh that could be useful let's go ahead and is there a namespace oh no this is still method information so let's grab the declared type uh it has namespace information right so webapp controller so let's grab the namespace we'll grab the home controller so the name and then we will add the action stuff all right so let's go ahead and cut we'll just string and cut this so we will take x uh declaring type we will grab the namespace so this might get a little bit messy well well also declaring type grab the name and this will need a dot here because namespace name actually maybe we can just string this let's to string this and see what we get okay and for now we will put this here as well so the x where we dump it all right so what do we have here uh web app controllers home controller and then we have system string so let's get rid of the system string the rest i think looks okay so let's go ahead uh grab the x a string yep this is where we want to split it by space and grab the last thing uh hopefully there is always the one if if there is more than one space so you know uh you use your own discretion here uh be careful all right uh let's go ahead and write this out right so the application that it comes from controller phone controller secret perhaps missing a dot so let's go ahead and run this and here we go so essentially we got more or less the mapping of where our controllers are and we can now represent the controllers that we have that we have written as code in the string format right so all the authorized actions we're basically just aggregating those by running the code that we have written through c-sharp as well right so that's just what it is we've written our application which is just some data we take that data we can put c-sharp into c-sharp essentially and we can now filter stuff through c-sharp so now that we have these strings let's go ahead uh send numerable strings what i'm going to do is i'm going to grab this bit here i'm going to go back into visual studio i'm going to go into my claims service and i'm just going to go ahead and return this here i'll say return okay i'm not going to cache this um do this yourself though that you you want to cache this sort of thing if you're going to take this approach so what i want to do here is i want to go into this authentic controller i want to put a breakpoint here and i just want to take a look through these this context and show you how you can basically investigate and basically do this implementation right so first of all let's take a look at if we get the claims in our view so service claims here we're going to return some claims i'm grabbing the service from dependency injection container by using the from services tag let's go ahead and run this so here we are let's go to home sign-in and here you can see the claims right so i can select a couple of claims i can sign in and i think it's worth putting a break point here and let's go ahead and submit this so for the claims here we have our claims so the three claims that we have selected web claim is just web app claim type and we're just going to sign in right so this is just going to return a cookie redirect to index we're going to turn up back to index and for the network or maybe the application cookies right there yeah there's our cookie right so for refresh we still have our cookie awesome i'm just going to delete this cookie make sure it doesn't mess with us or it was probably worth keeping that cookie in there nevertheless uh what i want to do is i want to access maybe home slash secret right and here is where the auth generated come our custom off handler comes in again i think it's episode four of my authorization authentication series so if you want to know more about authentication authorization.net core go watch that but here essentially we have this context which is of information about where we're trying to access so we should be able to find some information about where we're trying to access so we would go into resources obviously i took a look at this before doing this tutorial so i'm just picking the thing that i already know how to do but what you would do is you would slowly look through each one of these properties try to find something relevant and then try to find a way to access that and here i'm just going to try to recreate those steps so resource metadata result view here what you will find is this web app.controller home controller secret web app and in here is the information about the controller type info that you're trying to access right so it's the type of the controller and then we should also have the endpoint information so for example this method information so this is how we construct our claims we take the controller type we take the method type we trim it a little bit so there's a function for trimming and then we essentially create the claim so this is what we can do here as well so now all we need to do is just go into resources metadata and then just find a record that is about whatever this record is right so we don't know exactly how to filter it but we'll get there so without rambling on to for too long let's go ahead and try to first get to resources right so var resources equals context dot resources or resource and what will happen is if we try to do anything on the resource you will see that the resource is actually an object right so we don't actually know what type the resource is so initially you can see even the definition here is object we don't know what we're accessing so this is where we can go ahead and try to get the type of the resource again it's an object we get its type let's go ahead and rerun this i'm just going to grab a different endpoint that's a little bit easier to access so now if we take a look at the type we can see that the type is uh what's it called the the base type is http endpoint but this one is route endpoint okay so this is where we can basically use a little bit of just general c-sharp syntax to bind this resource so if uh resources or it is rather a resource so let's rename this source yeah there we go is a route endpoint that's what it was and then we'll name it re or we can just name it endpoint to be a little bit more succinct all right so we check is resource a route endpoint if it is do something with it okay otherwise what we're going to do is on the context we'll go ahead and call fail so we will basically we will not allow anyone to authorize here on the end point there was metadata so this is what we want to access so endpoint metadata and in there there were there was a collection of something right so metadata and here it's just a list right so this is like manipulating a list same as what we were doing with reflection here it's rather some metadata so if i remember correctly we didn't know exactly what type was the thing that we want to access so kind of want to get to that same place so what i'm going to do for metadata is i'm going to select in this get type i'm going to delete it because that was basically my learning i was trying to understand what to my my resource to and again metadata i'm not sure what it contains exactly so i'm gonna use a little bit of reflection to return a tuple with the actual type that i'm looking for and then the get type the thing that i want to find right or the thing that i'm looking for essentially right so the object itself inside the metadata and the type that it represents okay so i'm gonna put a breakpoint here on the end and before we run let's go ahead and assign this to it doesn't matter what this is because we're just trying to test here and yeah let's run this let's go ahead and run this so a let's take a look results for you so here what i'm trying to find is again that controller information and authorize attribute controller and controller action descriptor so that sounds like the information about my controller and here it is so manage controller secure this is the thing that i'm trying to access and the type is of controller action descriptor right so this is the thing that i'm looking for so controller action descriptor uh let's go ahead and grab firster default and we'll say x is controller action descriptor and that will be fine so controller ad action descriptor i think that also suffices a name let's go ahead once we got this bit we will basically take a look at its properties again or we could probably take a look at it through here so let's go ahead to local uh because i know removed the name so results it was number four number one so on here what we want to do is we want to get our controller type info and that's pretty much gonna get us what we have previously and then we want to have the method info which is again the information we had previously that we used to generate our claims in the claims service so we can once we get that we can pretty much reuse it okay so let's go ahead and oh not restart let's uh stop this so let's go ahead get the controller so con var controller equals controller ad and uh oh it's an object right so we actually because we know what object we're getting we can just cast it to that same object all right and let's put this on your line put this here uh so controller type info here what we'll essentially have is the x okay so or rather the declare declaring type of x okay so we will just have to to string this uh this bit i think we'll check and another thing is we want the method so the action we will go ahead and get the method info and that's the action so in our case it is just the x so let's go ahead and grab this can cap that we have here and let's grab our target claim put a semicolon here and let's see what we have to replace so for x and the declaration type i just want to put the controller in here and this x is going to be action okay so we just string the action split it grab the last and let's just make sure that what we have or what claim is required to access this action so that's what we want to find out and again here you can do stuff like as well as generate all the claims create like lookup tables for these actions so you don't have to repeat the reflection that you're doing okay so let's see what target claim we need so this will be webapp.controllers.managecontroller that secure the system string and this would be the claim that would be generated for that endpoint so if we go into link but if i still have it here right so this is one of those claims that's going to be needed so uh let's go ahead and wire this up right so the last bits is if the context user claims any if we have a claim where let's say the value and what's it called we want to do we need really need where we only have those so i mean we can we can put it for correctness uh or rather let's do it here so x type equals [Music] and here we will say and x value dot equals target claim we want to go ahead and on the context say succeeded pass the requirement and just return test completed okay so uh just to summarize on the context we grab the user that's trying to sign in we check its claims if there are any claims that are of webapp claim type and these claims or one of these claims equals the target claim okay so uh let's go ahead and remove these break points and see this work in its full glory so let's go ahead to home sign in i'm gonna pick the system secure string and i'm gonna pick the one on the home controller okay let's go ahead sign in i don't need this breakpoint anymore so i picked the one on the home controller so what i would have to do is i would have to go on home slash secret and here you can see i can navigate to this route so what would happen is if i went to manage and i went to secure i think it is i would get access denied okay so let's see what else is there is and i just tried to access secure uh on here let's try to manage slash allowed i'm gonna access that because no brainer it's allowed right we can go we can't go into secret either and can we go on to the secure yes we can right so if i just do a bunch of numbers because i override the default route this is how i access this page so if i wouldn't have had the token right if i just refresh this i get access tonight so that's essentially it on reflection and a little bit about the real world example but the real world example is just practice mainly the thing with the reflection to remember is that the code that you've written or the program is already data that you can manipulate and hopefully this will help you see your code as data and not as code that executes on data it does that too but the code that you've written is also still information that you can manipulate or rather derive from yeah hopefully you have enjoyed this video if you did like subscribe if you have any questions make sure to leave them in the comment section next video will be about expression trees i also stream on twitch wednesdays and sundays don't forget to join that and if you don't want to miss it join my discord channel i do a bunch of updates there but yeah hopefully i'll see in other episodes
Info
Channel: Raw Coding
Views: 17,749
Rating: undefined out of 5
Keywords: c#, asp.net core, tutorial, c# tutorial, asp.net core tutorial, explained, example, generator, reflection, what is reflection?, how to use reflection?, when to use reflection?
Id: cdG2JxuZvNI
Channel Id: undefined
Length: 39min 57sec (2397 seconds)
Published: Wed May 20 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.