AutoMapper - TypeConverter: Is there any chance to access the destination property from ResolutionContext - automapper

Currently I'm working with an Custom Type Converter class which worked good until a new issue appeared. (AutoMapper v11)
My Configuration:
cfg.CreateMap<string, MappedRelatedDataString>().ConvertUsing<MappedRelatedDataStringConverter>();
And the Converter class:
public class MappedRelatedDataStringConverter : ITypeConverter<string, MappedRelatedDataString>
{
public MappedRelatedDataStringConverter()
{
}
public MappedRelatedDataString Convert(string source, MappedRelatedDataString destination, ResolutionContext context)
{
return MappedRelatedDataString.CreateFromMapper(source, destination, context);
}
}
Now I digged through the passed context parameter,if it is possible to access the destination property of my mapping operation and noticed that there is no link to the member which is set up as mapping destination.
I hoped that it would be pretty easy to get access to the PropertyInfo.
Could anybody give me a hint how to get it working. The goal is to get access to some custom attributes (via PropertyInfo) on the destination side.
This is how my context instance looks during debugging:

Related

graph extension is marked as [PXOverride], but the original method with such name has not been found in PXGraph

I'm needing to adjust some of the field attributes for the Location.VCashAccountID field on the Vendors screen - AP303000. When I put the code below into a customization DLL, it compiles fine and there are not apparent issues on the screen. However, when I try to publish the customization project with the DLL included, I get an error.
Code:
public class VendorMaintDefLocationExtExt : PXGraphExtension<VendorMaint.DefLocationExt,
VendorMaint>
{
public void _(Events.CacheAttached<PX.Objects.CR.Standalone.Location.vCashAccountID> e) { }
}
Error:
"Method Boolean DoValidateAddresses(PX.Objects.CR.Extensions.ValidateAddressesDelegate) in graph extension is marked as [PXOverride], but the original method with such name has not been found in PXGraph"
What am I missing?
TIA!
The following implementation will override the vCashAccount attribute on AP303000
public class AAVendorMaintDefLocationExtExtension : PXGraphExtension<DefLocationExt, DefContactAddressExt, VendorMaint>
{
[PXMergeAttributes(Method = MergeMethod.Merge)]
[PXUIField(DisplayName = "I am override")]
public void _(Events.CacheAttached<PX.Objects.CR.Standalone.Location.vCashAccountID> e) { }
}
You will also require the following references
using PX.Data;
using PX.Objects.AP;
using static PX.Objects.AP.VendorMaint;
The result can be seen in the snip below
The main difficulty in this task was the multitude of graph extensions utilized by the page. Though it's a beneficial design to encapsulate functionality it can be finnicky to determine which order they should be declared in a new extension.
You're graph extension extends VendorMaint.DefLocationExt which contains DoValidateAddresses. Try just extending VendorMaint.

Xamarin Forms - CustomObject, XAML Initialization, Setter not called, DependencyProperty, I'm lost?

I have a problem and I searched a solution about it. Lucky, I red lot of post about it but I'm lost with the explaination I found. The initale problem is coming from a personal project about the polyline of the Xamarin.Forms.Map where the initialization is realized by a binding from the XAML part..
Let me be clear by an example :
I have an object CustomMap.cs which inherit from Xamarin.Forms.Map (This file is in the PCL part -> CustomControl/CustomMap.cs)
public class CustomMap : Map, INotifyPropertyChanged
{
public static readonly BindableProperty PolylineAddressPointsProperty =
BindableProperty.Create(nameof(PolylineAddressPoints), typeof(List<string>), typeof(CustomMap), null);
public List<string> PolylineAddressPoints
{
get { return (List<string>)GetValue(PolylineAddressPointsProperty); }
set
{
SetValue(PolylineAddressPointsProperty, value);
this.GeneratePolylineCoordinatesInner();
}
}
// ...
}
So the Xaml part of the page, where the control is called, looks like that:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:control="clr-namespace:MapPolylineProject.CustomControl;assembly=MapPolylineProject"
x:Class="MapPolylineProject.Page.MainPage">
<ContentPage.Content>
<control:CustomMap x:Name="MapTest" PolylineAddressPoints="{Binding AddressPointList}"
VerticalOptions="Fill" HorizontalOptions="Fill"/>
</ContentPage.Content>
</ContentPage>
The Csharp part:
public partial class MainPage : ContentPage
{
public List<string> AddressPointList { get; set; }
public MainPage()
{
base.BindingContext = this;
AddressPointList = new List<string>()
{
"72230 Ruaudin, France",
"72100 Le Mans, France",
"77500 Chelles, France"
};
InitializeComponent();
//MapTest.PolylineAddressPoints = AddressPointList;
}
}
So, everything is fine if I edit the PolylineAddressPoints from the object instance (if the commented part isnt' commented..), but if I init the value from the XAML (from the InitializeComponent();), it doesn't work, the SetValue, in the Set {}, isn't called..
I then searched on the web about it and get something about the Dependency Properties? or something like that. So I tried some solutions but, from WPF, so some methods, such as DependencyProperty.Register();. So yeah, I can't find the way to solve my problem..
I also though about something, if DependencyProperty.Register(); would exists in Xamarin.Forms, then it means I would have to do it for each values? Because, if every value has to be set by a XAML binding logic, it would not work, I would have to register every value, doesn't it?
I'm sorry if I'm not clear, but I'm so lost about this problem.. Please, do not hesitate to ask for more details, thank in advance !
I finaly got a solution just over here => Ignore the Binding initialization
Copy paste from Stackoverflow. This following answer was given by Stephane Delcroix, thank to him !
There are multiple questions in this:
Why is the property setter never called when using Xaml ?
Am I properly defining my BindableProperty ?
Why is my binding failing ?
Let me answer them in a different order.
Am I properly defining my BindableProperty ?
The BindableProperty declaration is right, but could be improved by using an IList<string>:
public static readonly BindableProperty PolylineAddressPointsProperty =
BindableProperty.Create(nameof(PolylineAddressPoints), typeof(IList<string>), typeof(CustomMap), null);
but the property accessor is wrong, and should only contains this:
public IList<string> PolylineAddressPoints
{
get { return (IList<string>)GetValue(PolylineAddressPointsProperty); }
set { SetValue(PolylineAddressPointsProperty, value); }
}
I'll tell you why while answering the next question. But you want to invoke a method when the property has changed. In order to do that, you have to reference a propertyChanged delegate to CreateBindableProperty, like this:
public static readonly BindableProperty PolylineAddressPointsProperty =
BindableProperty.Create(nameof(PolylineAddressPoints), typeof(IList<string>), typeof(CustomMap), null,
propertyChanged: OnPolyLineAddressPointsPropertyChanged);
And you have to declare that method too:
static void OnPolyLineAddressPointsPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
((CustomMap)bindable).OnPolyLineAddressPointsPropertyChanged((IList<string>)oldValue, (IList<string>)newValue);
}
void OnPolyLineAddressPointsPropertyChanged(IList<string> oldValue, IList<string> newValue)
{
GeneratePolylineCoordinatesInner();
}
Why is the property setter never called when using Xaml ?
The property, and the property accessors, are only meant to be invoked when accessing the property by code. C# code.
When setting a property with a BindablePrperty backing store from Xaml, the property accessors are bypassed and SetValue() is used directly.
When defining a Binding, both from code or from Xaml, property accessors are again bypassed and SetValue() is used when the property needs to be modified. And when SetValue() is invoked, the propertyChanged delegate is executed after the property has changed (to be complete here, propertyChanging is invoked before the property change).
You might wonder why bother defining the property if the bindable property is only used by xaml, or used in the context of Binding. Well, I said the property accessors weren't invoked, but they are used in the context of Xaml and XamlC:
a [TypeConverter] attribute can be defined on the property, and will be used
with XamlC on, the property signature can be used to infer, at compile time, the Type of the BindableProperty.
So it's a good habit to always declare property accessors for public BindableProperties. ALWAYS.
Why is my binding failing ?
As you're using CustomMap as bot View and ViewModel (I won't tell the Mvvm Police), doing this in your constructor should be enough:
BindingContext = this; //no need to prefix it with base.
As you're doing it already, your Binding should work once you've modified the BindableProperty declaration in the way I explained earlier.

Using MappingEngine throws exception

I'm maintaining an app which is using AutoMapper like this:
public class UserDomainService
{
public UserDTO GetUser(int id)
{
Mapper.Reset();
Mapper.CreateMap<User, UserDTO>();
var user = ....;
return Mapper.Map<User, UserDTO>(user);
}
}
This domain service is used by web-services.
I think it can be a problem when two web-service requests come in and on separate threads Reset and Map are called.
The Mapper can become in a state where the Map() fails.
I know I should probably setup CreateMap() mappings in Application_Start, but for now I am trying to do this:
public class UserDomainService
{
public UserDTO GetUser(int id)
{
var config = new AutoMapper.Configuration(new TypeMapFactory(), MapperRegistry.AllMappers());
config.CreateMap<User, UserDTO>();
var mapper = new MappingEngine(configuration);
var user = ....;
return mapper.Map<User, UserDTO>(user);
}
}
Leaving aside performance, is it anything which could potentially make the app crash?
Sometimes I am getting an exception like this:
System.ArgumentException: An item with the same key has already been added.
at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
at AutoMapper.TypeMapFactory.GetTypeInfo(Type type)
at AutoMapper.TypeMapFactory.CreateTypeMap(Type sourceType, Type destinationType, IMappingOptions options)
at AutoMapper.Configuration.CreateTypeMap(Type source, Type destination, String profileName)
at AutoMapper.Configuration.CreateMap[TSource,TDestination](String profileName)
at AutoMapper.Configuration.CreateMap[TSource,TDestination]()
Note that the above sample mapping is just an example.
I am using AutoMapper v1.1.0.188 in a 3.5 Net app.
EDIT:
There's a specific reason why it's not easy for me to put the configuration in the Application_Start.
I have different mapping requirements depending on the context. For example, for the same User to UserDTO, I need two different types of mapping.
It's the same problem described in this old question:
Link
https://github.com/AutoMapper/AutoMapper/wiki/Getting-started
Where do I configure AutoMapper?
If you're using the static Mapper method, configuration should only happen once per AppDomain. That means the best place to put the configuration code is in application startup, such as the Global.asax file for ASP.NET applications. Typically, the configuration bootstrapper class is in its own class, and this bootstrapper class is called from the startup method.

Create SharePoint (2010) ToolPart usable for more than one WebPart

I am using the basic instructions (here) for creating a property driven by a custom ToolPart.
All is good, except for the part where, in order to access the webpart property within the ApplyChanges method I must cast the "this.ParentToolPane.SelectedWebPart" back to a concrete "SimpleWebPart" class.
public override void ApplyChanges()
{
SimpleWebPart wp1 = (SimpleWebPart)this.ParentToolPane.SelectedWebPart;
// Send the custom text to the Web Part.
wp1.Text = Page.Request.Form[inputname];
}
Doing this means that I must pair each toolpart with a specific webpart. Is there a better way?
I cannot create an interface as there is no way of specifying a property in one.
I ineptly tried an passing an event/eventhandler during toolpart creation, but that did not update the webpart property when called.
I could create a base class for all the webparts that have a public "Text" property, but that is fugly.
I could also get desperate and crack open the this.ParentToolPane.SelectedWebPart reference with Reflection and call any properties named "Text" that way.
Either way, I am staring down the barrel of a fair bit of faffing around only to find out each option is a dead end.
Has anyone done this and can recommend the correct method for creating a reusable toolpart?
I have used an interface instead of a specific instance of a webpart.
private class IMyProperty
{
void SetMyProperty(string value);
}
public override void ApplyChanges()
{
IMyProperty wp1 = (IMyProperty)this.ParentToolPane.SelectedWebPart;
// Send the custom text to the Web Part.
wp1.SetMyProperty(Page.Request.Form[inputname]);
}
But this does not give a compile time warning that the toolpart requires the parent webpart to implement the IMyProperty interface.
The simple solution to that is to add a property of the IMyProperty interface in the toolpart constructor and call this reference instead of the this.ParentToolPane.SelectedWebPart property.
public ToolPart1(IContentUrl webPart)
{
// Set default properties
this.Init += new EventHandler(ToolPart1_Init);
parentWebPart = webPart;
}
public override void ApplyChanges()
{
// Send the custom text to the Web Part.
parentWebPart.SetMyProperty(Page.Request.Form[inputname]);
}
public override ToolPart[] GetToolParts()
{
// This is the custom ToolPart.
toolparts[2] = new ToolPart1(this);
return toolparts;
}
This works fine, but I cannot get over the feeling that there is something nasty in the underlying SharePoint code that may trip me up later.

Adding custom control with a collection property to a SharePoint Page Layout

I have created a custom control with a collection property per the example on How do you build an ASP.NET custom control with a collection property?
When the control is added to a common ASP.Net aspx page it works as expected. However, when added to a Page Layout in Sharepoint the following error is thrown:
Unable to cast object of type 'System.Web.UI.CollectionBuilder' to type 'System.Collections.Generic.List`1[mytypes.mytype]'.
The code is pretty much identical to the code provided by the example shown in the link above. I do not think the fault lies in the control as it works fine in a plain web project.
I dont think you can use generic lists in sharepoint. Use an ArrayList or customised List collection instead (use asp:ListItem as an exampe, it has its own collection type)
[ParseChildren(true, "Names")]
public class MyControl : Control {
private List<PersonName> names;
public MyControl() {
names = new List<PersonName>();
}
[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public List<PersonName> Names {
get { return this.names; }
}
}
public class PersonName {
public string Name { get; set; }
}
UPDATE
Ahh i see the problem now, it is not to do with the generic list, it is because of the way you are doing the initialization.
Create a private variable to hold the list private List<PersonName> names;
Ensure that the property does not have a setter

Resources