I am unclear about the rules regarding attributes and assembly dependencies.
Is it possible (and not a terrible idea) to annotate the types in an assembly with custom attributes from a NuGet package without introducing a run-time dependency on that NuGet package? Could clients use the types in the assembly without also needing to have the custom package's assemblies present?
I ask because My .NET application uses two packages:
A third party NuGet package called YamlDotNet for serializing types to YAML. It lets you control YAML serialization with custom attributes analogous to Microsoft's XML attributes (e.g. it has
YamlIgnoreAttributelike MS'XmlIgnoreAttribute)My own package, PackageA which does not depend upon YamlDotNet.
I want my app to serialize my types from PackageA using YamlDotNet. But they will not serialize correctly unless I do one of the following:
- annotate the types in PackageA with YamlDotNet custom attributes
- create annotated wrappers for PackageA types in the App to do the serialization for me.
I can do #2, but it would be easier to do #1. But I do not want to introduce a run-time dependency on YamlDotNet for all clients of PackageA. Ideally, I would like anybody using PackageA who also happens to be using YamlDotNet to get those attibutes for free and for them to be invisible to anyone else.
Is what I want possible?
CodePudding user response:
Attributes are a compile-time feature, you will always need reference to YamlDotNet in order to use one of its types as compile-time type metadata, unless you are open to doing things like generating your model classes in run-time (which is quite probably way more troublesome than having a one extra package reference).
This is a general problem where using attribute-driven features of a serializer pollutes the target assembly and couples it with that serializer.
There are three ways to address this:
- Accept this as a compromise
- Move YamlDotNet-specific into a separate assembly
- Have a separate serialization model
The first point should be quite clear - this is what you don't want and your first ssuggestion.
The second point could be creating YamlDotNet-specific type wrappers or type converters (if it supports such things) in a separate assembly so that the core assembly stays clean. This is your second suggestion, just with a twist of converters that may be more pleasant than wrapping everything from consumer perspective.
The third point is about creating DTOs/payloads in the core assembly so that you never have to use any serializer-specific attributes and the serialization just works out of the box. If you need to [YamlIgnore] properties, the model used for serialization probably also serves other purposes so this is basically just a separation of concerns. If you serialize your application model, you might find it impossible to provide backwards compatibility without affecting business logic at various places as a result.
