AutoMapper member-level transform not applied to destination value - automapper

Quick question about member-level value transformers. I have a string property mapped to a decimal property. I need to scale and round the destination value after it is mapped. I thought a value transformer would be the appropriate way to do this.
CreateMap<Source, Target>()
.ForMember(dest => dest.Rate, opts =>
{
opts.MapFrom(src => src.Rate);
opts.AddTransform(x => Math.Round(x * 100M, 2));
});
The value transformer never seems to be applied to the destination value (see fiddle, below for example)
I could also do
.ForMember(dest => dest.Rate, opts => opts.MapFrom(src => Math.Round(decimal.Parse(src.Rate) * 100, 2)));
but I'd prefer the member transform approach if possible as it uses AutoMapper's built-in string to decimal mapping convention not to mention it's a bit easier to read.
Am I misusing this feature? Any help or advice will be greatly appreciated!
Full example:
https://dotnetfiddle.net/PxoDGY
Thanks for taking a look.

Related

Search with different value in array each time

i need guide or help for how to search with different value 'airport' each time ‘values that define in array ‘ instead of type it hardcoded,
thanks in advance and i hope to find answer to use it in incoming scripts
it('select the origin Airport', function () {
for (let i in ['DXB dubai', 'AUH Abu Dhabi', 'JED Jeddah'])
// select the oragain
cy.get('[id="flights-search-origin-1"]')
.type('DXB dubai', {force: true}).should('have.value’,’one of the array's values ')````
I would use Array.prototype.map:
it('select the origin Airport', () => {
['DXB dubai', 'AUH Abu Dhabi', 'JED Jeddah'].map(airport => {
cy
.get('[id="flights-search-origin-1"]')
.clear().type(airport)
.should('have.value', airport);
})
})
Edit:
I've added a .clear before .type, and an assertion with the same value you've asked to type. Keep in mind this isn't an incredibly useful test, but it's what you've asked for.

How to access the data stored in this object?

I'm using BioPerl module to obtain a string from a set of parameters. I followed the HOWTO:Beginners page. The module apparently returns a hash object. How do I get the actual string out of the hash object?
use Bio::DB::GenBank;
use Data::Dumper;
my $gb = Bio::DB::GenBank->new(-format => 'Fasta',
-seq_start => 1,
-seq_stop => 251,
-strand => 1
-complexity => 1);
my $seq = $gb->get_Seq_by_acc('NG_016346');
my $sequence_string = lc($seq->seq());
my $seq_obj = Bio::Seq->new(-seq => $sequence_string,
-alphabet => 'dna' );
my $prot_obj = $seq_obj->translate;
print Dumper($prot_obj);
The data dumper prints the following:
$VAR1 = bless( {
'primary_seq' => bless( {
'length' => 83,
'_root_verbose' => 0,
'_nowarnonempty' => undef,
'seq' => 'RLCVKEGPWPAVEGTWSWG*HRPGSRACPRWGAPNSVQATSYTPSPTHAPFSVSPIPIC*MSLLEASCWPGSREDGARMSAGM',
'alphabet' => 'protein'
}, 'Bio::PrimarySeq' ),
'_root_verbose' => 0
}, 'Bio::Seq' );
How do I obtain 'seq' that is stored in $prot_obj?
I tried
print $prot_obj{'primary_seq'}{'seq'};
but it doesn't print anything. Data dumper printed the word bless. Maybe seq is a field of an object oriented variable.
The correct format for accessing object properties uses ->:
print $prot_obj->{'primary_seq'}->{'seq'};
I'm going to dispute the other answer, and say - the correct way to access object properties is not to do so, and use a method instead.
The reason for doing this is the whole point of OO. Which is to encapsulate chunks of your program, such that multiple developers can work with it concurrently, and the code scales because you can find where things are going wrong more easily.
This only works if you used published methods - the specified way of driving the object - because then you don't have to know what's going on behind the scenes. It also means the implementor is free to change what is going on - maybe simply validating, but maybe overloading or having different responses depending on another property within the object.
All this is subverted by direct access to object properties.
You shouldn't do it, even if perl will "let" you. Let's face it, perl will let you do many bad things.
Bio::PrimarySeq has a method call of seq. to retrieve the seq() attribute. Bio::Seq has an accessor for the primary sequence:
So:
$prot_obj -> seq();
I think would probably do it. (Although, the doc isn't exactly easy reading).
There is an accepted answer but I would also advise against poking around in the intervals of objects like that with the only exception being to see what kind of object is returned (or just use ref). Here is how I would approach the problem:
use 5.010;
use strict;
use warnings;
use Bio::DB::GenBank;
use Bio::Seq;
my $gb = Bio::DB::GenBank->new(
-format => 'Fasta',
-seq_start => 1,
-seq_stop => 251,
-strand => 1,
-complexity => 1
);
my $seq = $gb->get_Seq_by_acc('NG_016346');
my $seq_obj = Bio::Seq->new(
-id => $seq->id,
-seq => $seq->seq,
-alphabet => 'dna'
);
say join "\n", ">".$seq_obj->id, $seq_obj->translate->seq;
Running this gives you the translated FASTA record:
>gi|283837914:1-251
RLCVKEGPWPAVEGTWSWG*HRPGSRACPRWGAPNSVQATSYTPSPTHAPFSVSPIPIC*MSLLEASCWPGSREDGARMSAGM
The real benefit of using BioPerl is in combining the different classes together to solve problems with minimal (but also readable and reusable) code. There was also a minor typo in your code that would have been caught with strict and warnings pragmas enabled (that is my best advice).

How to remove default mapping of index without deleting its data of elasticsearch

I have some documents in Couch-base in which some field values are having space in it ("Ex. "New York").
I am not able to search it as exact match using term query.
I found that for searching the field values which are have space require some mapping like - index : not_analysed
and I have done the same
But when I am doing XDCR from couch base to elastic search .Couch base itself creates default mapping.Because of which I am not getting proper result.
So, is there any way by which we can delete default mapping without deleting its data?
Please refer the below code.
I have created and mapped index with dynamic template and then did the XDCR.
Now all string fields will be not_analysed.
IIndicesOperationResponse result = null;
if (!objElasticClient.IndexExists(elastic_indexname).Exists)
{
result = objElasticClient.CreateIndex(elastic_indexname, c => c.AddMapping<dynamic>(m => m.Type("_default_").DynamicTemplates(t => t
.Add(f => f.Name("string_fields").Match("*").MatchMappingType("string").Mapping(ma => ma
.String(s => s.Index(FieldIndexOption.NotAnalyzed)))))));
}
Technically you can change the mappings (check out the mappings API) but in practice I've found it more or less impossible because of conflicts with the existing mappings.
So:
1) Create mappings before indexing any data
2) Apply some of the ideas from this blog post: https://www.elastic.co/blog/changing-mapping-with-zero-downtime
I have got the solution
Here I have created and mapped index with dynamic template and then did the XDCR. Now all string fields will be not_analysed.It worked for me.
IIndicesOperationResponse result = null;
if (!objElasticClient.IndexExists(elastic_indexname).Exists)
{
result = objElasticClient.CreateIndex(elastic_indexname, c => c.AddMapping<dynamic>(m => m.Type("_default_").DynamicTemplates(t => t
.Add(f => f.Name("string_fields").Match("*").MatchMappingType("string").Mapping(ma => ma
.String(s => s.Index(FieldIndexOption.NotAnalyzed)))))));
}
Thanks
Mukesh Raghuwanshi

Re-using mappings in automapper

My existing solution has a lot of repetition like so:
config.CreateMap<IPublishedContent, ContactListingPage>()
.ForMember(n => n.Title, map => map.ResolveUsing(AppearanceManager.GetTitle));
config.CreateMap<IPublishedContent, NewsListingPage>()
.ForMember(n => n.Title, map => map.ResolveUsing(AppearanceManager.GetTitle));
Is there a way to remove this repetition?
I tried: using an interface:
config.CreateMap<IPublishedContent, IHaveTitle>()
.ForMember(n => n.Title, map => map.ResolveUsing(AppearanceManager.GetTitle));
But the actual map operations need to be to the concrete types, so this mapping is not used.
Note: I'm hoping to mix and match the mappings, so all pages have titles, and some pages have promotions, etc...
I tried:
Creating a custom type for title with implicit conversions to string, I think this 'would' work except for the fact that I actually need the IPublishedContent object as the input into the GetTitle method rather than the sub property PublishedProperty which it would be mapped from.
AutoMapper doesn't try to reuse mappings by design - mostly because I would confuse myself in these cases. You opt in to shared mappings:
Mapper.Initialize(cfg => {
cfg.CreateMap<IPublishedContent, IHaveTitle>()
.ForMember(n => n.Title, map => map.ResolveUsing(AppearanceManager.GetTitle));
cfg.CreateMap<IPublishedContent, ContactListingPage>()
.IncludeBase<IPublishedContent, IHaveTitle>();
cfg.CreateMap<IPublishedContent, NewsListingPage>()
.IncludeBase<IPublishedContent, IHaveTitle>();
});
I'm usually pretty careful about these because I don't necessarily want to introduce coupling on the ViewModel side. I've already removed the duplication through a shared resolver.

Can't listen to ItemChanged, ItemsAdded or ItemsRemoved on ReactiveList<T>

I have a ReactiveObject with a Property "A" of type "ReactiveList".
In my ViewModel I'd like to sum a property of "T" of every item in my list.
I got it working, while "A" not changes its value.
But all gets "out of sync", when I assign a new value to "A" (e.g. this.A = new ReactiveList();).
Does anyone have an idea how to solve this? I hope I explained my problem clear enough.
Instead of listening to A directly, listen to this:
this.WhenAnyObservable(x => x.A.ItemsChanged).Subscribe(...);
Whenever A changes, you'll resubscribe to A. Now, knowing when to reset to do a Sum, that's a bit more tricky. Here's the lazy yet more fool-proof way to do this:
Observable.Merge(
this.WhenAny(x => x.A, _ => Unit.Default),
this.WhenAnyObservable(x => x.Changed).Select(_ => Unit.Default))
.Select(_ => this.A.Sum(x => x.SomePropOnTheItem))
.DistinctUntilChanged()
.Subscribe(x => Console.WriteLine("Latest sum is {0}", x);
1 - I'd avoid assigning new Collections continuously as part of your logic, and rather use Clear(). Which should have the same impact in terms of GC.
2- If absolutely necessary, utilize a SerialDisposable and subsribe on the main object A
this.ObservableForProperty(p=> p.A).Subscribe(newAvalue=>{
someSerialDisposable.Disposable=
newAvalue.Changed.Subscribe(_=>this.Result=this.A.Sum(x=>x.T))
});
This would dispose previous deep subscriptions on A instances.

Resources