AutoMapper - why use Map over DynamicMap? - c#

Assuming the objects you're mapping with AutoMapper require no custom mappings, is there ever a point in doing this:
Mapper.CreateMap<Src, Dest>();
// ....
Mapper.Map(SrcObject, DestObj);
If no custom mappings are required, does the above approach gain you anything over just using DynamicMap without the need for any prior configuration?
Mapper.DynamicMap(SrcObject, DestObj);
I do understand that DynamicMap is required when you're mapping anonymous types, but I'm asking about whether DyanmicMap is ever not preferred for static types that require no custom mappings.

Been a while since I last used Automapper, but if I remember correctly:
In order to use Map, you need to specify those Maps explicitly first via CreateMap. Afterwards you can validate your Configuration by calling AssertConfigurationIsValid.
This happens right after launching your application rather than encountering an error mid execution (given that you create the mappings and validate on startup, which is recommended).
Also some types do not match 1:1, so you would want to specify the exact mappings, not sure if DynamicMap makes use of the Maps you have introduced manually, actually I think it does not.
Just checked, DynamicMap falls back on existing Maps in the current version up on github.
It's also a matter of performance since DynamicMap uses reflection more heavily than the Map method, since you have already specified the mapping configuration and most of it does not have to bee asserted on the fly anymore. Not sure if the new version of Automapper is performing caching in this regard by now though.

Related

How to create class out of structure definition using c#

I have a use case where we generate a lot of custom profiles based on the specific data modelling requirements. I am trying to find a way to create models out of it(c# classes) so that it can be serialized and deserialized and represented in the way that conforms to the profile constraints. I have seen many implementations to validate against profiles, but none on the generation aspect. Please let me know if there is a way to achieve this.
PS: All the resource types used are FHIR base resources.
Serialization and deserialization of FHIR instances is the same for all resources, regardless of profile. As such, there's no need for profile-specific code. Just use the generic .NET reference implementation. Profiles only change constraints, not what elements are named or how they appear in instances. If you're wanting profile-specific code to handle validation, there currently aren't any general-purpose solutions that do that - you'd have to create your own. However, the generic .NET reference implementation will perform the necessary validation if provided with the relevant StructureDefinitions.

When using protobuf-net, how do I know what fields will be updated (or have been updated) when using merge on an existing object

Using Protobuf-net, I want to know what properties of an object have been updated at the end of a merge operation so that I can notify interested code to update other components that may relate to those updated properties.
I noticed that there are a few different types of properties/methods I can add which will help me serialize selectively (Specified and ShouldSerialize). I noticed in MemberSpecifiedDecorator that the ‘read’ method will set the specified property to true when it reads. However, even if I add specified properties for each field, I’d have to check each one (and update code when new properties were added)
My current plan is to create a custom SerializationContext.context object, and then detect that during the desearalization process – and update a list of members. However… there are quite a few places in the code I need to touch to do that, and I’d rather do it using an existing system if possible.
It is much more desirable to get a list of updated member information. I realize that due to walking down an object graph that may result in many members, but in my use case I’m not merging complex objects, just simple POCO’s with value type properties.
Getting a delta log isn't an inbuilt feature, partly because of the complexity when it comes to complex models, as you note. The Specified trick would work, although this isn't the purpose it was designed for - but to avoid adding complexity to your own code,that would be something best handled via reflection, perhaps using the Expression API for performance. Another approach might be to use a ProtoReader to know in advance which fields will be touched, but that demands an understanding of the field-number/member map (which can be queried via RuntimeTypeModel).
Are you using habd-crafted models? Or are you using protogen? Yet another option would be to have code in the setters that logs changes somewhere. I don't think protogen currently emits partial method hooks, but it possibly could.
But let me turn this around: it isn't a feature that is built in right now, and it is somewhat limited due to complexity anyway, but: what would a "good" API for this look like to you?
As a side note: this isn't really a common features in serializers - you'd have very similar challenges in any mainstream serializer that I can think of.

How to apply Serializable attribute globally?

I have to apply [Serializable()] attribute for all classes, but I want to know is there any way to make classes Serializable globally instead of applying this attribute individually for all classes?
No, there isn't a way of applying this globally - you'd have to visit each type and add the attribute.
However: applying this globally is a really, really bad idea. Knowing exactly what you're serializing, when, and why is really important - whether this is for session-state, primary persistence, cache, or any other use-case. Statements like
I have to apply [Serializable()] attribute for all classes
tells me that you are not currently in control of what you are storing.
Additionally, since [Serializable] maps (usually) to BinaryFormatter, it is important to know that there are a lot of ways (when using BinaryFormatter) in which it is possible to accidentally drag unexpected parts of your model into the serialized data. The most notorious of these is "events", but: there are others.
When I see this type of question, what I envisage is that you're using types from your main data model as the thing that you are putting into session-state, but frankly: this is a mistake - and leads to questions like this. Instead, the far more maneagable approach is to create a separate model that exists purely for this purpose:
it only has the data that you need to have available in session
it is marked [Serializable] if your provider needs that - or whatever other metadata is needed for the sole purpose for which it exists
it does not have any events
it doesn't involve any tooling like ORM contexts, database connections etc
ideally it is immutable (to avoid confusion over what happens if you make changes locally, which can otherwise sometimes behave differently for in-memory vs persisted storage)
just plain simple basic objects - very easy to reason about
can be iterated separately to your main domain objects, so you don't have any unexpected breaks because you changed something innocent-looking in your domain model and it broke the serializer

Retrieve custom attributes of Type in .NET Standard

I'd like to use C#'s reflection and custom attributes to simplify registering a series of types with a central management class (i.e. it provides static methods taking a string key and invoking/retrieving the proper method/parameter for the associated type). Looking at other questions here and a couple places elsewhere, it seems like the best way of doing so is to simply iterate through all public types of the assembly -- since it's intended to be a library -- and check if each type has the proper attribute before adding the relevant values to the underlying Dictionaries. The reflection and iteration will definitely be slow, but I can live with it since it should only occur once.
Unfortunately, I can't figure out how to get an attribute from a type. For methods and assemblies, I can use CustomAttributeExtensions.GetCustomAttribute<MyAttribute>(base) from System.Reflection.Extensions, but that doesn't provide an overload for Type; the same for Assembly.GetCustomAttribute(Assembly, Type) and the .IsDefined(...) methods used in this question. Other suggestions use methods on the Type itself that, from the documentation, seem to be loaded from mscorelib.dll, but it didn't seem to be showing up in Intellisense even after adding the reference and I'm not sure how that .dll interacts with .NET Standard, anyway (as in, does it reduce the ability to run on arbitrary platforms at all?)
Am I missing something obvious, or is it really this hard to get an Attribute back off of a Type?
Try typeof(YourType).GetTypeInfo().GetCustomAttributes();

How to verify that automapper mappings have been created for all uses?

I'd like to have a test that verifies that, for each use of Automapper.Mapper.Map<T1,T2>(), that there is a corresponding mapping configuration (AutoMapper.Mapper.CreateMap<T1,T2>()) in my Bootstrapper.
I was just about to go down the road of using Roslyn to interface with the compiler and find all usages of the Map<> method and then try to map using those instances. Although that would do the trick, I think I'd rather use something that already exists.
Does this exist? If not, is there a better way to do this than with Roslyn?
You're treading too deep into meta-programming.
Best thing you can do is to contain your mapped classes to one or several namespaces, and check that there are mappings for all classes in those namespaces. For this you won't need Roslyn, Cecil or any such thing.
If you're abandoning compile-time checks, at least you have to put in place some conventions, and if your conventions are well defined, you can verify them.
Problem is you can't be sure - there are loads of cases where it's not deterministic (e.g. a model of type Y might be passed to AutoMapper downcast to an object.
You should provide coverage of the actual consumption of the mappings as part of your normal code coverage.
Whether that means unit tests for every mapping method is a different question...

Categories