✅ Passing subset of options when resolving instance with MS.DI (Working example with DryIoc)
@viceroypenguin Continuing the discussion we were having last night about moving away from DryIoc, I am currently using
scope.Use(foo)
when resolving instances at startup based on config and looking to simplify and just use MSDI. I created an example project to better illustrate how I'm currently wiring everything up
https://github.com/ksladowski/device-registration-exampleGitHub
GitHub - ksladowski/device-registration-example
Contribute to ksladowski/device-registration-example development by creating an account on GitHub.
43 Replies
nit: switch to
.slnx
file instead of .sln
file asap. 🙂Oh yeah my actual project is
.slnx
, I just threw this together quicklyyou open to switching validation libraries?
Yeah for sure
Are you talking about IV? I thought that was just for Handler parameters
nope. that's it's intended use, but techniclly there's only one class in IV that requires IH. the rest of IV works fully independently of IH
there's an argument to be made that IV should have two packages, one for basic support and one for the glue class that binds IH and IV together
your options class can look like this:
with no other validator class necessary. 🙂
So is it just the behavior part that binds IH and IV together?
correct
That's much nicer, I'll definitely switch those over
And that all just works with
services.AddOptions<T>().ValidateOnStartup()
right?Gotcha. Sweet well thats super nice. I was already using IV for endpoints anyway so this is a no brainer
sweet. now back to the original mission... haha
ok, real question: why not just hand out
IDeviceRegistry
all over th place and let it return devices?
or you could:
I'm doing this:
then you really don't need the dryioc container at all. just have
DeviceRegistry
receive your options and intiialize all of the devices in the constructorI guess what I was trying to avoid was this: So if I need to add a new type of device I don't need to change code in multiple places
fair enough. do this...
I typically register them with
Injectio
attributes, and before that I did something worse:
And scoped isn't really correct here, they probably should be transient
DryIoc doesn't like transients that are disposable thoughtransient and singleton are effectively the same when the thing asking for it is singleton, so better to just register them singleton
But I might need multiple
DeviceA
s that are distinctahhh... good to know
ah, got it. hold on a sec
Yeah I put the options in
appsettings.json
honestly, this switch is probably your best bet. keyed services won't work the way i want them to either.
you could even isolate to a method that you source generate, if you wanted
be a really easy generator too.
you could do it by reflection too if you wanted
if that was easier
reflection just isn't on my shelf of "i'm going to use that" anymore. 🙂
I might go the source gen route then. I have another really basic one for json polymorphic types. I wouldn't be opposed to just keeping dryioc either since it appears I actually have one of the niche cases where I need the functionality it adds over MS.DI, but idk how I feel about dropping a preview version into production code, especially since I can't seem to find a changelog between 5.4.3 and 6.0.0-preview
yeah, i just haven't found that i use the dryioc features anymore
Also, important but unrelated question now that I think about it - IH Behaviors are meant for cross-cutting concerns. I have a couple decorators too that are business logic but I want to keep the code separate from the remaining business logic that it wraps. Are Behaviors appropriate here or would i need to keep Decorator<> too
that's totally appropriate
behaviors can be what you want them to be. anything that's cross-cutting. whether that's infra (logging), biz concerns, or something that spreads both (like authz)
like https://github.com/viceroypenguin/VsaTemplate/blob/master/Api/Features/Todos/Authorization/TodoAuthorizationBehavior.cs is technically crossing both biz logic and infra.
Got it. So do you not use
TransformResult
? You touched on this the other day and I'm still a bit confused. Sorry to keep throwing more questions at youSorry to keep throwing more questions at youall good. anythign to spread the mission of IP... 😄
So do you not use TransformResult?nope. i'll argue the best way to use it for those that do want to use it, but i have no desire for it personally
Other than adding the openapi annotations, I guess I just don't get why separate the business logic from the endpoint logic if the business logic isn't able (or recommended) to be reused elsewhere anyway
the reason one would use the transformresult is if they wanted the endpoint code to be purely business logic, unaware of web at all. so you return a regular command object from your handleasync, and let the transform turn it into something useful
my opinion is that there are endpoints that are just plain awkward to separate biz code from the fact that it's a web endpoint (for example, if you want to return a streamresult of some kind)
besides, i don't bother with typedresults. i just return the object i need, and throw an exception for various semi-expected cases. the exceptions are usually custom exceptions that then expose http status code and message, and the eproblem details handler picks those values up and uses them
Okay so thats the piece I don't really get how it's wired up.
It's endpoint filters or something like that right?
* https://github.com/viceroypenguin/VsaTemplate/blob/master/Api/Infrastructure/Exceptions/ExceptionStartupExtensions.cs this piece wires up the connection between an unhandled exception and the problem details exposed by the api endpoint
* https://github.com/viceroypenguin/VsaTemplate/blob/master/Api/Infrastructure/Exceptions/VsaTemplateException.cs base class for exceptions
* https://github.com/viceroypenguin/VsaTemplate/blob/master/Api/Features/Shared/Exceptions/NotFoundException.cs example case of an exception
Okay, and problem details is just an ASP.NET thing I wasn't aware of?
yes
technically a web thing, that aspnet now has support for, but yes.
Gotcha. Just about things I see in your template now - does [LoggerMessage] provide anything other than organization? Like it still uses serilog via the Microsoft.Logging.Extensions adapter right
source generated performance
https://learn.microsoft.com/en-us/dotnet/core/extensions/logger-message-generator
Oh interesting, I wasn't ever aware of that either
Okay, well I can't think of anything else, I really appreciate you taking the time to look at this and answer my questions
you bet!
Question - I have a lot of stuff like this:
A lot of my validations have conditionals and unless I'm missing something, I think doing
AdditionalValidations
would be a significant increase in boilerplate compared to IV, no? 🙁do me a favor, open a new issue? i do havee an answer for you though 🙂
@KevS fyi i meant in #help. not on IV. hope you're not creating a GH issue... haha
Yep I got it, just posted it haha. Just had to take the dog outside quick
Honestly I just ended up with this:
It's not ideal cause the properties initialize like this
But since I'm validating the options I think it's okay
why this instead of generating the
switch
?I was just trying it out. I have 3 different constructs that behave this way and seemed like it might be simpler but after sleeping on it, not so sure anymore.
It feels like its a lot less code and I don't really see a downside
Okay i actually needed a validator too so I tried again, if I open an issue in code-review later would you mind taking a look?
of course