This is a first time i have been bogged down like this by automapper. I am trying to map a result set returned by the stored procedure to my entity. L2S has the result set available, it is one row for my current test, can by multiple. Usually automaper exception is thrown when a return type is nullable if not properly handled. I have left it as is and also changed it to some value but in both cases i am still getting the exception. I am missing some thing very basic here but can't put my hands on it. Need second pair of eyes... Thanks.
Code Call
var annualReportOutreachEditionResult = ClientsContext.AnnualReportOutreachEditionInfoGet(fice, reportYear).ToList();
if (annualReportOutreachEditionResult != null)
{
annualReportOutreachEditionDetail = Mapper.Map<List<AnnualReportOutreachEditionInfoGetResult>, List<AnnualReportOutreachEditionDetail>>(annualReportOutreachEditionResult);
AnnualReportOutreachEditionDetail Entity
public class AnnualReportOutreachEditionDetail
{
public string Edition { get; set; }
public DateTime MailDate { get; set; }
public string CardId { get; set; }
}
AnnualReportOutreachEditionInfoGetResult L2S Entity
public partial class AnnualReportOutreachEditionInfoGetResult
{
private string _Edition;
private System.Nullable<System.DateTime> _MailDate;
private string _CardId;
public AnnualReportOutreachEditionInfoGetResult()
{
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Edition", DbType="VarChar(50)")]
public string Edition
{
get
{
return this._Edition;
}
set
{
if ((this._Edition != value))
{
this._Edition = value;
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_MailDate", DbType="Date")]
public System.Nullable<System.DateTime> MailDate
{
get
{
return this._MailDate;
}
set
{
if ((this._MailDate != value))
{
this._MailDate = value;
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_CardId", DbType="Char(9)")]
public string CardId
{
get
{
return this._CardId;
}
set
{
if ((this._CardId != value))
{
this._CardId = value;
}
}
}
}
MApping
I have also checked/tested defaultvalue for date and my exception is still there. That is the only nullable type.
public static void MapAnnualReportOutreachEditionDetail()
{
Mapper.CreateMap<AnnualReportOutreachEditionInfoGetResult, AnnualReportOutreachEditionDetail>()
;
}
Exception Details
AutoMapper.AutoMapperMappingException was unhandled by user code
Message=Trying to map System.Collections.Generic.List`1[[Nrccua.LinqToSql.AnnualReportOutreachEditionInfoGetResult, Nrccua.LinqToSql, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] to System.Collections.Generic.List`1[[Nrccua.BusinessEntities.AnnualReportOutreachEditionDetail, Nrccua.BusinessEntities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].
Exception of type 'AutoMapper.AutoMapperMappingException' was thrown.
Source=AutoMapper
StackTrace:
at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context)
at AutoMapper.MappingEngine.Map(Object source, Type sourceType, Type destinationType)
at AutoMapper.MappingEngine.Map[TSource,TDestination](TSource source)
at AutoMapper.Mapper.Map[TSource,TDestination](TSource source)
at Nrccua.LinqToSql.DataAccess.AnnualReportAccess.GetAnnualReportOutreachEditionDetails(String fice, String reportYear) in C:\Users\tahir\Documents\DATA\Projects\NrccuaWebSite\NrccuaWebSiteTahirj\Core\BusinessEntities\Nrccua.LinqToSql\DataAccess\AnnualReportAccess.cs:line 211
at Nrccua.Repositories.AnnualReportRepository.GetAnnualReportOutreachEditionDetails(String fice, String reportYear) in C:\Users\tahir\Documents\DATA\Projects\NrccuaWebSite\NrccuaWebSiteTahirj\Core\Repositories\Nrccua.Repositories\AnnualReportRepository.cs:line 199
at RepositoryTests.AnnualReportTest.GetOutreachDetailsTest() in C:\Users\tahir\Documents\DATA\Projects\NrccuaWebSite\NrccuaWebSiteTahirj\Core\Tests\RepositoryTests\AnnualReportTest.cs:line 55
InnerException: AutoMapper.AutoMapperMappingException
Message=Trying to map Nrccua.LinqToSql.AnnualReportOutreachEditionInfoGetResult to Nrccua.BusinessEntities.AnnualReportOutreachEditionDetail.
Exception of type 'AutoMapper.AutoMapperMappingException' was thrown.
Source=AutoMapper
StackTrace:
at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context)
at AutoMapper.Mappers.EnumerableMapperBase`1.Map(ResolutionContext context, IMappingEngineRunner mapper)
at AutoMapper.Mappers.CollectionMapper.Map(ResolutionContext context, IMappingEngineRunner mapper)
at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context)
InnerException: AutoMapper.AutoMapperMappingException
Message=Trying to map Nrccua.LinqToSql.AnnualReportOutreachEditionInfoGetResult to Nrccua.BusinessEntities.AnnualReportOutreachEditionDetail.
Missing type map configuration or unsupported mapping.
Exception of type 'AutoMapper.AutoMapperMappingException' was thrown.
Source=AutoMapper
StackTrace:
at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context)
InnerException:
It was a problem at my end, I forgot to add the definition for my mapper method. Fixed.
Related
I am having some trouble with custom enum marshaling with Moxy and JSON. My use case is that I have a large object model that includes enumerations that normally should provide a normal enumerated value, a "code", and a description. The source of this data has only the "code", so I need to be able to unmarshal instances of these enums using only the code (e.g.
{"companyCode":{"code":"PI"}}.
However, I should also be able to marshal and unmarshal all three fields:
{"companyCode":
{"value":"Private",
"code":"PI","description":
"Private Ins"
}
}
I am using an adapter that looks like this:
public class CodeEnumXmlAdapter<E extends Enum<E> & CodeEnum> extends XmlAdapter<CodeEnumImpl,E> {
public static <T extends Enum<T> & CodeEnum> T getFromName(Class<T> clazz, String name) {
if (name == null) return null;
T[] values = clazz.getEnumConstants();
for (T t : values) {
if (name.equals(t.name())) {
return t;
}
}
return null;
}
public static <T extends Enum<T> & CodeEnum> T getFromCode(Class<T> clazz, String code) {
if (code == null) return null;
T[] values = clazz.getEnumConstants();
for (T t : values) {
if (code.equals(t.getCode())) {
return t;
}
}
return null;
}
public static <T extends Enum<T> & CodeEnum> T getFromString(Class<T> clazz, String aString) {
if (aString == null) return null;
T[] values = clazz.getEnumConstants();
for (T t : values) {
if (aString.equals(t.getCode()) || aString.equals(t.name()) || aString.equals(t.getDescription())) {
return t;
}
}
return null;
}
#Override
public E unmarshal(CodeEnumImpl value) throws Exception {
if (value == null) return null;
String valueString = value.getValue();
if (valueString == null)
valueString = value.getCode();
if (valueString == null)
valueString = value.getDescription();
if (valueString == null)
return null;
Type generic = ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
return getFromString((Class<E>)generic, valueString);
}
#Override
public CodeEnumImpl marshal(E value) throws Exception {
return value == null ? null : new CodeEnumImpl(value);
}
}
This converts from a an enum like this:
import org.apache.commons.lang3.StringUtils;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlJavaTypeAdapter(CompanyCode.Adapter.class)
public enum CompanyCode implements CodeEnum {
// Changed "Commmercial" to "Client" based on inputs from ...Greg, Tamil
Client("CM", "Client"), Medicare("MC", "Medicare"), Medicaid("MD",
"Medicaid"), Private("PI", "Private Ins"), Patient("PT", "Patient");
private String code;
private String description;
private CompanyCode(String code, String label) {
this.code = code;
this.description = label;
}
public String getDescription() {
return description;
}
public String getCode() {
return code;
}
public static CompanyCode fromCode(String code) {
if (StringUtils.isEmpty(code)) {
return null;
}
for (CompanyCode freq : values()) {
if (freq.getCode().equalsIgnoreCase(code)) {
return freq;
}
}
throw new IllegalArgumentException("Invalid CompanyCode code: " + code);
}
public String toString() {
return description;
}
public static class Adapter extends CodeEnumXmlAdapter<CompanyCode> {}
}
and uses and intermediate type like this:
import javax.xml.bind.annotation.XmlElement;
/**
* Created by Jeffrey Hoffman on 6/24/2015.
*/
public class CodeEnumImpl {
String value;
String description;
String code;
public CodeEnumImpl() {
}
public <E extends Enum<E> & CodeEnum> CodeEnumImpl(E value) {
if (value != null) {
this.value = value.name();
this.description = value.getDescription();
this.code = value.getCode();
}
}
#XmlElement
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#XmlElement
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#XmlElement
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
#Override
public String toString() {
return value == null ? null : value.toString();
}
}
This is working fine with straight XML and JAXB. However, when I try to use Moxy, I get an exception like this:
Exception Description: The object [Private Ins], of class [class
com.labcorp.phoenix.biz.enums.CompanyCode], could not be converted to
[class java.lang.Object]. Internal Exception: Exception
[EclipseLink-115] (Eclipse Persistence Services -
2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DescriptorException Exception
Description: No conversion value provided for the attribute [Private].
Mapping:
org.eclipse.persistence.oxm.mappings.XMLDirectMapping[companyCode-->companyCode/text()]
Descriptor: XMLDescriptor(com.labcorp.phoenix.eligibility.Root -->
[DatabaseTable(root)]) at
org.eclipse.persistence.exceptions.ConversionException.couldNotBeConverted(ConversionException.java:87)
at
org.eclipse.persistence.internal.jaxb.XMLJavaTypeConverter.convertObjectValueToDataValue(XMLJavaTypeConverter.java:178)
at
org.eclipse.persistence.oxm.mappings.XMLDirectMapping.convertObjectValueToDataValue(XMLDirectMapping.java:511)
at
org.eclipse.persistence.oxm.mappings.XMLDirectMapping.getFieldValue(XMLDirectMapping.java:330)
at
org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue.marshalSingleValue(XMLDirectMappingNodeValue.java:62)
at
org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue.marshal(XMLDirectMappingNodeValue.java:58)
at
org.eclipse.persistence.internal.oxm.NodeValue.marshal(NodeValue.java:102)
at
org.eclipse.persistence.internal.oxm.record.ObjectMarshalContext.marshal(ObjectMarshalContext.java:59)
at
org.eclipse.persistence.internal.oxm.XPathNode.marshal(XPathNode.java:393)
at
org.eclipse.persistence.internal.oxm.XPathNode.marshal(XPathNode.java:368)
at
org.eclipse.persistence.internal.oxm.XPathObjectBuilder.buildRow(XPathObjectBuilder.java:238)
at
org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:118)
at
org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:1)
at
org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:743)
at
org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:1124)
at
org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:869)
... 7 more Caused by: Exception [EclipseLink-115] (Eclipse
Persistence Services - 2.5.0.v20130507-3faac2b):
org.eclipse.persistence.exceptions.DescriptorException
It seems like a bug in moxy, because my adapter converts to a non-enum type, so there should not be a nestedConverter that deals with enums.
I managed to reproduce your issue with 2.5.0. It's most probably bug which has been fixed already. Unable to find the bug in Eclipse Bugzilla, but the same code works correctly with 2.6.0. Are you able to upgrade to latest MOXy?
when partially unmarshalling an XML, I am receiving the following error message:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 6 counts of IllegalAnnotationExceptions
Property id is present but not specified in #XmlType.propOrder
this problem is related to the following location:
at public java.lang.String xmlFields.Example.getId()
at xmlFields.Example
Property text is present but not specified in #XmlType.propOrder
this problem is related to the following location:
at public java.lang.String xmlFields.Example.getText()
at xmlFields.Example
Property type is present but not specified in #XmlType.propOrder
this problem is related to the following location:
at public java.lang.String xmlFields.Example.getType()
at xmlFields.Example
Property ID appears in #XmlType.propOrder, but no such property exists. Maybe you meant id?
this problem is related to the following location:
at xmlFields.Example
Property Text appears in #XmlType.propOrder, but no such property exists. Maybe you meant text?
this problem is related to the following location:
at xmlFields.Example
Property Type appears in #XmlType.propOrder, but no such property exists. Maybe you meant type?
this problem is related to the following location:
at xmlFields.Example
at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:451)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:283)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:126)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1148)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:130)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:248)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:235)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:445)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:637)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
at extractFromXML.ReadFromXML.convertToJavaObject(ReadFromXML.java:72)
at extractFromXML.ReadFromXML.main(ReadFromXML.java:97)
I have the follwing implementation (extracting only a part of the xml seem to work):
#XmlRootElement
#XmlType(propOrder={"ID", "Text", "Type"})
public class Example {
private String id;
private String text;
public Example() {
super();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
private String type;
}
And this is the part of the xml file:
......<ExampleOptions><Example> <ID>ETZH8</ID> <Text>hello</Text> <Type>VAR</Type> </Example></ExampleOptions>.......
Any ideas?
Thanks
UPDATE #1
I adapted the suggestions by Blaise, but still getting only null values:
Example [id=null, text=null, type=null, getId()=null, getText()=null, getType()=null, getClass()=class xmlFields.Example, hashCode()=18467372, toString()=xmlFields.Example#119ca2c]
UPDATE #2
This is my current code:
#XmlRootElement
#XmlType(propOrder={"id", "text", "type"})
public class Example {
private String id;
private String text;
private String type;
public Example() {
super();
}
#XmlElement(name="ID")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlElement(name="Text")
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
#XmlElement(name="Type")
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
I can't publish the whole XML. It is a nested XML file.
UPDATE #3
The problem is, I only try to extract a part of my xml. Therefore, I have the following main function:
public static void main(String[] args) throws Exception {
try {
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xml = new StreamSource(POI_XML);
XMLStreamReader xsr = xif.createXMLStreamReader(xml);
xsr.nextTag();
while(xsr.hasNext()) {
if(xsr.isStartElement() && xsr.getLocalName().equals("Example")) {
break;
}
xsr.next();
}
JAXBElement<Example> jb;
try {
JAXBContext context = JAXBContext.newInstance(Example.class);
Unmarshaller um = context.createUnmarshaller();
jb = um.unmarshal(xsr, Example.class);
xsr.close();
Example stations = jb.getValue();
System.out.println(stations.toString());
} catch (JAXBException e) {
e.printStackTrace();
}
} catch (FactoryConfigurationError e) {
e.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
}
}
Moreover, I just tried to extract just an example of one deep path in the nested XML. It looks more than:
<ExampleOptions><Example> <ID>ETZH8</ID> <Text>hello</Text> <Type>VAR</Type> </Example></ExampleOptions><ConnectionCount>1</ConnectionCount><Info>abc</Info>.....
UPDATE #4
I just checked the marshalling example with the following error message:
Exception in thread "main" javax.xml.bind.UnmarshalException
- with linked exception:
[org.xml.sax.SAXParseException; systemId: file:///D:/proj/ConvertXMLToPostgres/input2.xml; lineNumber: 1; columnNumber: 39; Vorzeitiges Dateiende.]
The propOrder is based on the field/property names and not the elements that they are mapped to. You just need to change your propOrder:
#XmlType(propOrder={"id", "text", "type"})
The stack trace also points you in this direction:
Property ID appears in #XmlType.propOrder, but no such property exists. Maybe you meant id?
this problem is related to the following location:
at xmlFields.Example
Property Text appears in #XmlType.propOrder, but no such property exists. Maybe you meant text?
this problem is related to the following location:
at xmlFields.Example
Property Type appears in #XmlType.propOrder, but no such property exists. Maybe you meant type?
this problem is related to the following location:
at xmlFields.Example
For More Information
I have written more about this on my blog:
http://blog.bdoughan.com/2012/02/jaxbs-xmltype-and-proporder.html
UPDATE #1
Thanks. I changed the code, but I am getting null values.
The element names in your XML don't match the default names that JAXB derives from your property names, so you will need to override it with an #XmlElement annotation.
#XmlElement("ID")
public String getId() {
return id;
}
Debugging Tip:
When you run into an issue when unmarshalling, try populating your object model and marshalling it to XML to see what XML is expected.
UPDATE #2
Demo
When I run the following against your updated Example class everything works for me. Does it work for you as well?
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Example.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
StreamSource source = new StreamSource("input.xml");
JAXBElement<Example> result = unmarshaller.unmarshal(source, Example.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(result, System.out);
}
}
Input/Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Example>
<ID>ETZH8</ID>
<Text>hello</Text>
<Type>VAR</Type>
</Example>
UPDATE #3
When I run the Java code from your UPDATE #3 against the model from your UPDATE #2 with the following XML everything works:
<ExampleOptions><Example> <ID>ETZH8</ID> <Text>hello</Text> <Type>VAR</Type> </Example></ExampleOptions>
Can you update your code in UPDATE #3 to include System.out.println(xsr.getNamespaceURI()); to see if there are any namespaces in play?
while(xsr.hasNext()) {
if(xsr.isStartElement() && xsr.getLocalName().equals("Example")) {
System.out.println(xsr.getNamespaceURI());
break;
}
xsr.next();
}
Any idea what might cause the error "Expressions mapping from methods not supported yet." when trying to map two objects? I cannot find any reference to this error anywhere.
EDITED---
I have more information. I have a property in my DTO declared as:
public LookupItem RegionType { get; set; }
However, when I invoke the mapping, it generates the error, "Expressions mapping from methods not supported yet.".
However, if I change the string in the property name "Type" to anything else like "Typeo" or "ASDF", the mapping succeeds. In other words, if change the property name to "RegionTypeo". Am I breaking any convention rules here? There seems to be something wrong with including the string "Type" in my property name.
Below is the generated error:
Result Message:
Test method Rep.Tests.PlanServiceTest.GetBuildings threw exception:
System.NotImplementedException: Expressions mapping from methods not supported yet.
Result StackTrace:
at AutoMapper.PropertyMap.ResolveExpression(Type currentType, Expression instanceParameter)
at AutoMapper.QueryableExtensions.Extensions.CreateMemberBindings(IMappingEngine mappingEngine, Type typeIn, TypeMap typeMap, Expression instanceParameter)
at AutoMapper.QueryableExtensions.Extensions.CreateMapExpression(IMappingEngine mappingEngine, Type typeIn, Type typeOut, Expression instanceParameter)
at AutoMapper.QueryableExtensions.Extensions.CreateMapExpression(IMappingEngine mappingEngine, Type typeIn, Type typeOut)
at AutoMapper.QueryableExtensions.Extensions.<>c__DisplayClass12.<CreateMapExpression>b__0(TypePair tp)
at System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey key, Func2 valueFactory)
at AutoMapper.Internal.DictionaryFactoryOverride.ConcurrentDictionaryImpl2.GetOrAdd(TKey key, Func2 valueFactory)
at AutoMapper.QueryableExtensions.Extensions.CreateMapExpression[TSource,TDestination](IMappingEngine mappingEngine)
at AutoMapper.QueryableExtensions.ProjectionExpression1.ToTResult
at Rep.Services.PlanService.GetBuildings() in c:\Dev\REP\Rep\Services\PlanService.cs:line 369
at Rep.Tests.PlanServiceTest.GetBuildings() in c:\Dev\REP\Rep.Tests\PlanServiceTest.cs:line 50
Based on the source code, you can see that the exception is thrown when you try mapping functions on your objects:
public ExpressionResolutionResult ResolveExpression(Type currentType, Expression instanceParameter)
{
Expression currentChild = instanceParameter;
Type currentChildType = currentType;
foreach (var resolver in GetSourceValueResolvers())
{
var getter = resolver as IMemberGetter;
if (getter != null)
{
var memberInfo = getter.MemberInfo;
var propertyInfo = memberInfo as PropertyInfo;
if (propertyInfo != null)
{
currentChild = Expression.Property(currentChild, propertyInfo);
currentChildType = propertyInfo.PropertyType;
}
else
{
throw new NotImplementedException("Expressions mapping from methods not supported yet.");
}
}
else
{
var oldParameter = CustomExpression.Parameters.Single();
var newParameter = instanceParameter;
var converter = new ConversionVisitor(newParameter, oldParameter);
currentChild = converter.Visit(CustomExpression.Body);
currentChildType = currentChild.Type;
}
}
return new ExpressionResolutionResult(currentChild, currentChildType);
}
Based on OP clarification, I cannot reproduce the problem with the following:
public class Class1
{
public string StringType { get; set; }
public Func<Class1> FuncType { get; set; }
public Class1 Class1Type { get; set; }
}
public class Class2
{
public string StringType { get; set; }
public Func<Class1> FuncType { get; set; }
public Class1 Class1Type { get; set; }
}
/* ... */
AutoMapper.Mapper.CreateMap<Class1, Class2>();
var c1 = new Class1() { Class1Type = new Class1(), FuncType = () => new Class1(), StringType = "Class1" };
var c2 = AutoMapper.Mapper.Map<Class1, Class2>(new Class1());
I have an Activity where I declared a InArgument without a type (because I want to know the type of the Expression at design time).
When I execute the activity I get this error in var contentTelegram line:
"The argument of type '<type>' cannot be used. Make sure that it is declared on an activity."
Here is my code:
public InArgument Content { get; set; }
protected override PlcMessage Execute(CodeActivityContext context)
{
try
{
var contentTelegram = Content.Get(context);
return new PlcMessage();
}
catch (Exception ex)
{
throw;
}
}
Here is what I did:
The workflow runtime needs to know about the used types in arguments, so the cacheMetadata is the key to make it work, CacheMetadata uses reflection to know about arguments, notice that only works for simple cases.
public sealed class MyActivity: CodeActivity
{
private RuntimeArgument outMyRuntimeArgument;
// Define an activity input argument of type string
public OutArgument MyUntypedArgument { get; set; }
protected override void CacheMetadata(CodeActivityMetadata metadata)
{
outMyArgument= new RuntimeArgument("MyUntypedArgument", MyUntypedArgument.ArgumentType, ArgumentDirection.Out);
metadata.Bind(MyUntypedArgument, outArgument);
metadata.AddArgument(outMyArgument);
}
protected override void Execute(CodeActivityContext context)
{
context.SetValue(outMyRuntimeArgument, Activator.CreateInstance(Type));
}
}
is there any problem with this kinda registration via structure map??
static public class ContainerBootstrapper
{
static public void BootstrapDefaultContainer(bool test = false)
{
StructureMap.ObjectFactory.Initialize(x =>
{
x.Scan(p =>
{
p.AssemblyContainingType<IPropertyType>();
p.AddAllTypesOf<IPropertyType>();
// p.AddAllTypesOf<IPropertyType>().NameBy(c => c.Name);
});
});
}
public interface IPropertyType : IIdentityObject, IPriority
{
string PropertyName { get; set; }
ObjectType ObjectType { get; }
string DisplayName { get; set; }
IEntityType EntityType { get; set; }
IList<IPropertyRuleObject> RuleObjects { get; set; }
void AddRuleObject(IPropertyRuleObject ruleObject);
}
public abstract class PropertyTypeBase : PersistentObject, IPropertyType
{
public PropertyTypeBase()
{
}
public PropertyTypeBase(string propertyName, string displayName)
{
PropertyName = propertyName;
DisplayName = displayName;
}
....
}
public class StringType : PropertyTypeBase
{
private ObjectType _objectType;
public StringType()
{
_objectType = new ObjectType(typeof(string));
}
public StringType(string propertyName, string displayName)
: base()
{
PropertyName = propertyName;
DisplayName = displayName;
}
public override ObjectType ObjectType
{
get { return _objectType; }
}
}
when ContainerBootstrapper.BootstrapDefaultContainer(); execute I see this line of error:
StructureMap Exception Code: 200
Could not find an Instance named "StringType" for PluginType Azarakhsh.Domain.Core.AdaptiveObjectModel.Interface.IPropertyType
the calling code:
public IPropertyType GetPropertyType(IIdentityObject identityObject, string name)
{
string[] Properties = name.Split('.');
object Result = identityObject;
foreach (var Property in Properties)
Result = Result.GetType().GetProperty(Property).PropertyType.Name;
IPropertyType propertyType = StructureMap.ObjectFactory.GetNamedInstance<IPropertyType> (Result + "Type");
if (propertyType==null)
throw new Exception("Property type not found");
return propertyType;
}
what is the problem?
You are trying to get a named instance, but from what I can see of the code you have provided, you dont name your instances. The line of code that name your instances is commented out.
But even if you would just use the ObjectFactory.GetInstance<IPropertyType>(); here, you would have got an error because structuremap dont know what constructor to use. There are several solutions to theis problem.
Change your design so you only have one constructor
Mark your default constructor with the [DefaultConstructor] attribute, then it will work.
You can register it with objectFactory manually with something like this:
x.For().Use().Ctor("propertyName").Is("someValue").Ctor("displayName").Is("someValue");
You can write a custom registrationconvention as described here