AutoMapper treats known class instance as `Object` - automapper

I have a test that checks that objects match after conversion but automapper 10 has started saying I am missing a map from Object -> ExistingClass when the source object is defined.
Not an easy one to google, ahs anyone seen this before?
//maps defined elsewhere and checked
CreateMap<AnimalDBO, AnimalDTO>(MemberList.Destination)
CreateMap<AnimalDTO, AnimalBase>(MemberList.Destination)
var animal = new AnimalDBO
{
Ear_Tag = "IE301228071641"
};
82: AnimalDTO dto = mapper.Map<AnimalDTO>(animal);
83: var ab = mapper.Map<AnimalBase>(dto); //Automapper errors with Object -> AnimalBase
The object error:
AutoMapper.AutoMapperMappingException : Missing type map configuration or unsupported mapping.
Mapping types:
Object -> AnimalBase
System.Object -> HukNetCore.Animal.Domain.AnimalBase
Stack Trace:
lambda_method(Closure , Object , AnimalBase , ResolutionContext )
EarTagTests.StringToEarTagIE() line 83
I've tracked the error down to this method
private TDestination MapCore<TSource, TDestination>(
TSource source, TDestination destination, ResolutionContext context, Type sourceType = null, Type destinationType = null, IMemberMap memberMap = null)
{
return ConfigurationProvider.GetExecutionPlan<TSource, TDestination>(MapRequest())(source, destination, context);
MapRequest MapRequest()
{
var runtimeTypes = new TypePair(source?.GetType() ?? sourceType ?? typeof(TSource), destination?.GetType() ?? destinationType ?? typeof(TDestination));
var requestedTypes = new TypePair(typeof(TSource), typeof(TDestination));
return new MapRequest(requestedTypes, runtimeTypes, memberMap);
}
}
And these are the object created in that method
new TypePair(source?.GetType() ?? sourceType ?? typeof(TSource), destination?.GetType() ?? destinationType ?? typeof(TDestination))
"AnimalDTO", "AnimalBase"
ContainsGenericParameters: false
DestinationType: {Name = "AnimalBase" FullName = "Animal.Domain.AnimalBase"}
IsGeneric: false
IsGenericTypeDefinition: false
SourceType: {Name = "AnimalDTO" FullName = "Animal.Domain.DTO.AnimalDTO"}
SourceType: {Name = "AnimalDTO" FullName = "Animal.Domain.DTO.AnimalDTO"}
error CS0726: ':' is not a valid format specifier
new TypePair(typeof(TSource), typeof(TDestination))
"Object", "AnimalBase"
ContainsGenericParameters: false
DestinationType: {Name = "AnimalBase" FullName = "Animal.Domain.AnimalBase"}
IsGeneric: false
IsGenericTypeDefinition: false
SourceType: {Name = "Object" FullName = "System.Object"}

Thanks Lucian,
In my case it turned out to be that when the DI was being set up I was not loading an assembly into memory before calling services.AddAutoMapper(refs);.
Check your ref list and check all the dlls your expect are loaded

Related

Flutter access model attribute using dynamic key [duplicate]

I'm trying to access a class value by using a variable previously defined in dart, but I keep getting the error the operator [] isn't defined for the class
In Javascript I would access an object value using a variable like this:
let movie = {
movieTitle : 'Toy Story',
actor: 'Tom Hanks'
}
let actorName = 'actor';
console.log(movie[actorName]); // <- what I'm trying to replicate in dart
// expected output: Tom Hanks
Here is what I've tried and is throwing that error
class Movie {
String name;
String actor;
String producer;
}
void main() {
var movieTitle = new Movie();
movieTitle.name = 'Toy Story';
movieTitle.actor = 'Tom Hanks';
print(movieTitle.actor); <- prints out Tom Hanks as expected
var actorName = 'actor';
print(movieTitle[actorName]); <- throws error
}
I expect to be able to use a variable on the fly to access the value.
A trivial use case for me would be if I had a a list of Movie classes, where some actors and producers are null, I would like to filter on either non null actors or producer with a function like so:
List values = movieList.where((i) => i.actor != "null").toList(); // returns all Movies in movieList where the actor value isn't the string "null"
var actorIsNull = 'actor';
List values = movieList.where((i) => i[actorisNull] != "null").toList(); // throws error
You can createn a toMap() function in your Movie class and access properties using [] operator
class Movie {
String name;
String actor;
String producer;
Map<String, dynamic> toMap() {
return {
'name': name,
'actor' : actor,
'producer' : producer,
};
}
}
Now Movie class properties can be accessed as:
Movie movie = Movie();
movie.toMap()['name'];
You cannot access class members by a string containing their name. (Except with mirrors - outside the scope of this answer.)
You could remove the class altogether and just use a Map<String, String>.
Map<String, String> movie = {
'movieTitle': 'Toy Story',
'actor': 'Tom Hanks',
}
You could add some bool methods on the class.
bool hasNoActor() => actor == null;
...
List values = movieList.where((m) => !m.hasNoActor()).toList();
Or, you could pass a lambda to your mapper.
Movie movieTitle = Movie()
..name = 'Toy Story'
..actor = 'Tom Hanks';
Function hasActor = (Movie m) => m.actor != null;
List values = movieList.where(hasActor).toList();

How to get Opportunity Relations in Sales Order

In Opportunity screen, the definition of the data view for Relations is simply :
public CRRelationsList<CROpportunity.noteID> Relations;
When a Sales Order is raised from the Opportunity. I'd like to display the Relations defined from the source Opporunity in another tab. And I'm just struggling how to write the the data view and pass the Opportunity noteid.
public CRRelationsList<???>Relations;
Thanks !
The generic type in dataviews often resolve to the current record.
In CRRelationsList class the generic type is named TNoteField:
public class CRRelationsList<TNoteField> : PXSelect<CRRelation>
where TNoteField : IBqlField
ssuming the dataview is declared as CRRelationsList<CROpportunity.noteID>.
The generic type value will be resolved like this Caches[typeof(CROpportunity)].Current.NoteID.
protected virtual void CRRelation_RefNoteID_FieldDefaulting(PXCache sender, PXFieldDefaultingEventArgs e)
{
// Get a cache object of type CROpportunity
var refCache = sender.Graph.Caches[BqlCommand.GetItemType(typeof(TNoteField))];
// Get the NoteID field value of the current CROpportunity object
e.NewValue = refCache.GetValue(refCache.Current, typeof(TNoteField).Name);
}
So to set DAC.Field of CRelationsList<DAC.field> you would do:
// In a graph extension (PXGraphExtension)
Base.Caches[typeof(DAC)].Current.Fied = ???;
// Or in graph (PXGraph)
Caches[typeof(DAC)].Current.Fied = ???;
If current DAC object is null you need to insert a record in a dataview or directly in the cache object.
I'm not sure re-using CRRelationsList list is the best approach if you want to simply display records because it does much more than that. It should be possible to extract the select request out of it and directly substitute the TNoteField value:
private static PXSelectDelegate GetHandler()
{
return () =>
{
var command = new Select2<CRRelation,
LeftJoin<BAccount, On<BAccount.bAccountID, Equal<CRRelation.entityID>>,
LeftJoin<Contact,
On<Contact.contactID, Equal<Switch<Case<Where<BAccount.type, Equal<BAccountType.employeeType>>, BAccount.defContactID>, CRRelation.contactID>>>,
LeftJoin<Users, On<Users.pKID, Equal<Contact.userID>>>>>,
Where<CRRelation.refNoteID, Equal<Current<TNoteField>>>>();
var startRow = PXView.StartRow;
int totalRows = 0;
var list = new PXView(PXView.CurrentGraph, false, command).
Select(null, null, PXView.Searches, PXView.SortColumns, PXView.Descendings, PXView.Filters,
ref startRow, PXView.MaximumRows, ref totalRows);
PXView.StartRow = 0;
foreach (PXResult<CRRelation, BAccount, Contact, Users> row in list)
{
var relation = (CRRelation)row[typeof(CRRelation)];
var account = (BAccount)row[typeof(BAccount)];
relation.Name = account.AcctName;
relation.EntityCD = account.AcctCD;
var contact = (Contact)row[typeof(Contact)];
if (contact.ContactID == null && relation.ContactID != null &&
account.Type != BAccountType.EmployeeType)
{
var directContact = (Contact)PXSelect<Contact>.
Search<Contact.contactID>(PXView.CurrentGraph, relation.ContactID);
if (directContact != null) contact = directContact;
}
relation.Email = contact.EMail;
var user = (Users)row[typeof(Users)];
if (account.Type != BAccountType.EmployeeType)
relation.ContactName = contact.DisplayName;
else
{
if (string.IsNullOrEmpty(relation.Name))
relation.Name = user.FullName;
if (string.IsNullOrEmpty(relation.Email))
relation.Email = user.Email;
}
}
return list;
};
}

Edit value on mapping with AutoMapper

I'm trying to refactor my project and use automapper to map view model to entity model. Here is my my current code. I have used Guid.NewGuid(), GetValueOrDefault() and DateTime.Now. How can I edit those value on mapping?
var product = new Product
{
Id = Guid.NewGuid(),
Name = model.Name,
Price = model.Price.GetValueOrDefault(),
ShortDescription = model.ShortDescription,
FullDescription = model.FullDescription,
SEOUrl = model.SEOUrl,
MetaTitle = model.MetaTitle,
MetaKeywords = model.MetaKeywords,
MetaDescription = model.MetaDescription,
Published = model.Published,
DateAdded = DateTime.Now,
DateModified = DateTime.Now
};
then here is my map code
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<Product, ProductCreateUpdateModel>().ReverseMap();
});
Tell me if I understood you right. You want to create AutoMapper configuration, but some of the properties you want to map manually? In this case, you can do following:
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<Product, ProductCreateUpdateModel>()
.ReverseMap()
.ForMember(product => product.Price, expression => expression.MapFrom(model => model.Price.GetValueOrDefault()))
.ForMember(product => product.DateAdded, expression => expression.UseValue(DateTime.Now))
.ForMember(product => product.DateModified, expression => expression.UseValue(DateTime.Now));
});
If not, please, specify your question.

ValidationResult throws : "Object reference not set to an instance of an object". when passing back choices

Please find the below exception.
Stack Trace: Exception: Exception caught:
'Microsoft.Bot.Builder.FormFlow.FormCanceledException1' in
mscorlib.dll ("Object reference not set to an instance of an
object."). Exception caught:
'Microsoft.Bot.Builder.FormFlow.FormCanceledException1' in
mscorlib.dll ("Object reference not set to an instance of an object.")
Hi, I am trying to generate form flow and during validation, If user enters wrong text then I am passing choices to select from but bot however throws above exception and emulator hangs.
Below is the example
.Field(nameof(RegistrationForm.ModelNumber), validate: async (state, value) =>
{
var modelsSuggestion = PimsServiceClient.GetModelSuggestion();
ValidateResult validateResult = new ValidateResult()
{
IsValid = modelsSuggestion.Any(m => m.ToLower().Equals(value?.ToString().ToLower())),
Value = value,
Choices = new List(modelsSuggestion.Select(s => new Choice { Value = s } }))
};
/* Do some database stuff */
return validateResult;
})
I tried again and figred out that i had to provide all the property values for choices like below
var choices = new List<Choice>();
choices.Add(new Choice { Description = new DescribeAttribute("Tes1", null, "Tes1", null, null), Value ="Tes1", Terms = new TermsAttribute("Tes1", "T1")});
choices.Add(new Choice { Description = new DescribeAttribute("Test2", null, "Test2", null, null), Value = "Test2", Terms = new TermsAttribute("Test2", "T2") });
ValidateResult validateResult = new ValidateResult()
{
/*if modelSuggestion != null && modelsSuggestion.Any()*/
IsValid = false,
Value = value,
Choices = choices
};

Cannot assign a value of type 'GeoPoint?' to a value of a value of type 'AnyObject?'

Hi I have this code on view did load:
PFGeoPoint.geoPointForCurrentLocationInBackground { (geopoint: PFGeoPoint?, error: NSError?) -> Void in
if error == nil {
println(geopoint)
var user = PFUser.currentUser()
user["location"] = geopoint
var query = PFUser.query()
query!.whereKey("location", nearGeoPoint:geopoint!)
query!.limit = 10
query!.findObjectsInBackgroundWithBlock({ (users, error) -> Void in
var accepted = PFUser.currentUser()["accepted"] as! [String]
var rejected = PFUser.currentUser()["rejected"] as! [String]
for user in users {
the errors are:
user["location"] = geopoint
Cannot assign a value of type 'PFGeoPoint?' to a value of type 'AnyObject?'
next error is the same on this two lines
var accepted = PFUser.currentUser()["accepted"] as! [String]
var rejected = PFUser.currentUser()["rejected"] as! [String]
and is AnyObject is not convertible to '[String]'
and the last error is on the line
for user in users {
'[AnyObject]?' does not have a member named 'Generator'
I hope you guys can help me with them
You need unwrap your optional to access the reference it contains (and call methods on it).
Try this:
if let unwrappedUsers = users { for user in unwrappedUsers { ... } }
Iff users is not empty/nil/None, its reference will be unwrapped to unwrappedUsers.

Resources