I have the following classes:
public class A{}
public class AA : A {public int aa{get;set;}}
public class AAA : A {public int aaa{get;set;}}
public class B{}
public class BB : B {public int bb{get;set;}}
public class BBB : B {public int bbb{get;set;}}
and this is my mapping:
Mapper.CreateMap<A,B>().include<AA,BB>().include<AAA,BBB>();
Mapper.CreateMap<AA,BB>();
Mapper.CreateMap<AAA,BBB>();
I was under the assumption that automapper will understand the hiearchy and map the appropriate derived class. But i wasn't able to get it with the codes below. The mapped entities are always the base class, in this case - B.
Please note I have a Repository factory which will determine the return type of GetAll().
var list = myRepo.GetAll() //this returns IEnumerabe<AA> or IEnumerable<AAA>
var newlist = Mapper.Map<IEnumerable<B>>(list); //I wanted to use "B" here due to the fact I will have many inherited classes of B. I don't want to restrict to a specific child class of B.
OK. The codes above should work. Unfortunately, I was using automapper 4.1.1 and there was a bug -https://github.com/AutoMapper/AutoMapper/issues/819.
Related
Disclaimer: First I have to say that I have a different background - Java/Scala and Typescript is definitely not my biggest strength.
I have two fairly complex classes and pre-defined contract which maps each property from class class A to class B. I have to convert instance of class A to class B and vice versa on demand. I know this could be done with a static mapper which does the translation in code, but I was wondering if there are some packages/techniques which could easy my pain. I already checked https://github.com/typestack/class-transformer, but it doesn't seem to cover everything I want.
Requirements:
Some array fields from one class could be transformed or flattened before mapped to the other class.
Class A is a simple {[key:string], string} map, while B's fields are more complex and type inferred from the contract.
Key in class A might be mapped to key Y in class B.
An example A->B:
class A {
"key1" = "1234"
"key2" = "text"
"key3" = "10/07/2021"
"key5" = "otherText"
}
and after conversion
class B {
"newKey1" = 1234,
"newKey2" = "text",
"newKey3" = Date(..),
"key4": {
"key5": "otherText"
}
Any tips, suggestions will be very much appreciated.
I'm writing an AST Transformation and I need to create a field inside my AST which has the #Delegate annotation.
I have a class A which I apply the annotation to.
#MyAnnotation
class A{ }
MyAnnotation has MyAnnotationASTTransformation where I'm trying to create a field of type B and add it the class A. Desired result after compilation:
class A{
#Delegate
B object = new B()
}
Inside my ASTTransformation I tried AstBuildet.buildFromString
List<ASTNode> astNodeList = new AstBuilder().buildFromString(
CompilePhase.CONVERSION,
String.format(
"class A{\n" +
" #Delegate\n"+
" B b = new B()\n"+
"}\n"
)
)
List<FieldNode> fieldNodeList =((ClassNode)astNodeList.get(1)).getFields()
classNode.addField(fieldNodeList.get(0))
Adding this to my project gives the following error:
8: class Delegate is not an annotation in #Delegate
Without #Delegate it works just fine, can I add the #Delegate manually somehow inside my ASTTransformation?
I am using Nomin for mapping tasks. As taken from the documentation of Nomin it should be able to map fields with the same name by itself in case automapping has been activated. When activating it, it causes an infinite loop exception.
I have the following:
mappingFor a: CoinsOnMarketPlace, b: Coin
// automap() // when deactivated it works fine, when activated infinite loop
a.coin.name = b.name
a.coin.rank = b.rank
a.priceUSD = b.priceUSD // Could be automapped
a.priceBTC = b.priceBTC // Could be automapped
...
Exception:
org.nomin.core.NominException: ./net/hemisoft/ccm/repository/coinmarketcap2coin.groovy: Recursive mapping rule a = b causes infinite loop!
One thing worth adding regarding your use case - this Recursive mapping rule a = b causes infinite loop! exception is thrown because you use groovy classes in your mapping rule. Nomin uses ReflectionIntrospector and what's important:
It performs getting/setting properties using accessor methods which are called through the Java reflection mechanism. ReflectionIntrospector uses supplied NamingPolicy instance to determine accessor methods. JbNamingPolicy is used by default, this implementation cerresponds the JavaBeans convention. Its InstanceCreator named ReflectionInstanceCreator instantiates objects using Class.newInstance().
Source: http://nomin.sourceforge.net/introspectors.html
A simple Groovy class like:
class Entity {
String name
String somethingElse
}
gets compiled to a Java class that implements GroovyObject providing following methods:
public interface GroovyObject {
Object invokeMethod(String var1, Object var2);
Object getProperty(String var1);
void setProperty(String var1, Object var2);
MetaClass getMetaClass();
void setMetaClass(MetaClass var1);
}
In this case ReflectionInstanceCreator combined with automap() resolves following mappings:
a.property = b.property
and
a = b
where a = b mapping comes from MetaClass getMetaClass() getter method I suppose, because there is no mapping like a.metaClass = b.metaClass resolved. a.property = b.property gets resolved because of Object getProperty(String var1) method.
Solution
This problem can be solved by specifying explicitly ExplodingIntrospector for your mapping script that:
It performs getting/setting properties using a class field immediately through through the Java reflection mechanism and may be useful in case when domain object don't provide accessors for their properties. Supplied instance creator is ReflectionInstanceCreator.
Source: http://nomin.sourceforge.net/introspectors.html
All you have to do is to add
introspector exploding
right below mappingFor a: ..., b: ... header. For example:
import mypackage.Entity
import mypackage.EntityDto
mappingFor a: Entity, b: EntityDto
introspector exploding
automap()
a.test2 = b.test1
Tested with two Groovy classes, worked like a charm. Hope it helps.
I have two classes, say ClassA and ClassB, and I want to map them with ClassC. How can I do it?
ClassA has only 1 property and ClassB has 5 properties. ClassC has 6 properties.
Situation is something as below:
Public ClassC MapRequest(classA id, ClassB someProperties){
_mapper.Map<ClassC>(id);
_mapper.Map<Classc>(someProperties);
retrun type of ClassC;
}
There is overload of Map method available.
var objClassC = _mapper.Map<ClassA, ClassC>(id);
// You need to pass above instance to next call.
_mapper.Map<ClassB, ClassC>(someProperties, objClassC );
Hope this helps.
I have a class and interface is implemented as below :
Class1<T> : IClass1<T>
now I am creating the property in Class2 :
Public IClass<?> MyClassProperty {get; set;}
what should be the type I need to give to this generic property , so I can assign it from the different class3.
Please suggest me.
Have you tried object? After that you can get the real type with typeof(value) (value is available in set)