❔ How to Package Multiple Versions of a Library Targeting Different Dependency Versions into a Nuget
I am working on a C# library (
mylib
) which has a dependency on another library (thatlib
).
Now, the problem is, that thatlib
has breaking changes between versions 1.0
and 2.0
, and I need to support both versions of thatlib
in my library.
I need to create two different versions of mylib
, each targeting different versions of thatlib
, and package them into a single NuGet package. Here are the version ranges I am targeting:
1. mylib_v1
targeting thatlib
versions [1.0,2.0)
2. mylib_v2
targeting thatlib
versions [2.0,5.0)
I want to achieve this ideally using a single .csproj
file without creating separate projects for each version. My goal is to ensure that consumers of my library get the correct version of mylib
based on the version of thatlib
they are using.98 Replies
you wouldn't bundle them together in the same package
you would release two different versions of your package
But thats also far from ideal.
What if i want to release an update for my package?
then you update it?
the nuspec format simply doesn't support specifying multiple versions of the same dependency
My initial idea was to follow the versioning of
thatlib
, but that would prevent me from following my own schedule/needs for updates
Thats what ive guessedso, like
the breaking changes in
thatlib
they affect YOU, or you're worried about them affecting your consumers?Its just that
oof, they actually DROPPED the overload?
"customers" well i want my lib to be available to as much ppl as possible
WELL
its complicated
i actually hacked the lib
the class is internal
F
I MEAN
I could just use the 47 version and if it does not work, i could use reflection as a fallback
that's possible
but its SLOWWWWW
i mean
"slow"
you'd only have to do it once
one initial reflection to lookup the delegate, then you cache that and reuse it
well yes but its complicated...again xDD
anyway, to me, this seems like.... not that big of a deal
its way more complex than u think
it's fairly normal for a library publisher to update their own dependencies
the purpose of my lib is that the complete runtime only lives for under a sec
and consumers are required to update them as well, to be able to update your lib
tab completion for spectre console to be exact
okay
so
you're like a plugin?
yes
gotcha
like a super illegal hack plugin which uses internals
illegal?
"illegal"
well
accessing internals = "illegal"
like, are you breaking their ToS in some way?
nonono
okay, okay
nothing like that
so
its just not nice 😄
what you said earlier is basically the way to go
track THEIR version numbers
if they release 1.0, you have your plugin that is 1.0 (or whatever)
yea but what if i want to extend my library...i cant just go out of sync
if you add new features, you increment, 1.0.1, 1.1.0, etc.
if they update to 2.0, you do the same
and what you CAN possibly do
if you want to add new features, you can maintain two streams
if you have something new to add, you release 2.0.1, and 1.0.2
or whatever
Its actually funny, they dont leave space for my numbers
a little documentation on the NuGet page should clarify "if you're using Spectre X, you use the latest subversion of Y"
etc.
i mean i could do -preview.26.[MYNUMBER]
huh?
i mean how would i publish an update a version of my library which is already on
0.47.1-preview.0.26
you aren't limited to only pushing versions newer than what you've done already
you can push 2.0.1 and then turn around and push 1.0.1
I'm pretty sure
the version number is just a field in the nuspec
i thought i would follow their versioning scheme
What i meant with "illegal", i cant use the class here
But its ok there
right
https://github.com/aelij/IgnoresAccessChecksToGenerator
If ure interested, found it a couble of days ago
GitHub
GitHub - aelij/IgnoresAccessChecksToGenerator: Generates reference ...
Generates reference assemblies where all the internal types & members become public, and applies the IgnoresAccessChecksTo attribute - GitHub - aelij/IgnoresAccessChecksToGenerator: Generat...
still kinda hyped 😄
yes, that's a fairly common trick
Like u know how it works?
I have to admit, i dont quite
i have an idea
but im not sure
you patch the target dependency, develop against that, and the swap it out, yeah?
I think it mocks it at dev time but apart from that, thats what my impression is yea
yeah
Dirty, dirty trick 😄
yeah, i would never do this in a library
just use reflection
it is not worth building multiple versions to do otherwise
Tried, was too much work.
I might be using reflection to activate that class tho
swaps the DLL you reference for one where everything is public
then adds a (completely unsupported!) attribute that the runtime recognizes to allow you to access private/internal things from that assembly at runtime
reflection wouldn't be any better, except that you can maybe detect if some APIs don't exist, and fall back to different ones
either way, if you're using internals, you're breaking when the target makes minor updates
reflection is better because its actually something supported by the runtime can be removed at any time
it was added silently and can be taken away in the same way
So the runtime would actually care?
care about what?
if they stopped recognizing the attribute, yes
accessing the internals of other assemblies
it's not the runtime that recognizes it, it's Roslyn
no, its not
roslyn does not recognize IgnoreAccessChecksTo
in fact they have refused to do so
then how does code compile when you're using internal members?
the generator swaps the assembly
for one with everything public
then it has roslyn reference that
hmm, okay
I thought the generator just attached
InternalsVisibleTo
to the assembly
so
InternalsVisibleTo
actually has nothing to do with any of thisyeah
so, what was your point about the runtime?
IgnoreAccessChecksTo can stop existing
at any moment
so what?
if it does, the runtime will just throw when you access internal things
it doesn't do anything here
yes, it does
how?
roslyn isnt the only thing that checks accessibility
the runtime does too
so what?
the public assembly is not kept for runtime
its still private at runtime
and doesn't have
InternalsVisibleTo
on ityes
how is it relevant?
okay
IgnoreAccessChecksToAttribute replaces InternalsVisibleTo
oh, right
its a secret sibling attribute
did I screw that up?
*crazy secret sibling
if the runtime stops supporting it, it will now realize you have no permission to access the things are are accessing
Lets hope that never happens
god github search sucks
GitHub
Compiler support for IgnoresAccessChecksToAttribute by aelij · Pull...
The IgnoresAccessChecksToAttribute is the reverse of the InternalsVisibleToAttribute - it allows an assembly to declare assemblies whose internals would be visible to it. The attribute class isn...
@just eepy I managed to do this hack without
IgnoresAccessChecksToAttribute
i am simply able to abuse the InternalsVisibleTo
attribute*CommandModel is internal
yeah but that means modifying the runtime version of the DLL you're referencing
which isn't always an option
What does that mean?
I created a library that has that exact name
ah
I see what you mean now
yeah that works, as long as they don't change that
they won't
otherwise i would just not release an update for that version
my plan would be to add this lib to the nuget ... do you have a better idea?
can i host multiple assemblies in a dll?
ik ILMerge but does the merged library have the advantages of the
InternalsVisibleTo
attribute?Was this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.