Xamarin Android Binding incorrect method override name - xamarin

Quite a strange problem in Xamarin.Android bindings. I have a java class defined as follows:
// Java world
public abstract class BaseRenderableSeries<TX extends Comparable<TX>,
TY extends Comparable<TY>,
TRenderPassData extends ISeriesRenderPassData,
TDataSeries extends IDataSeries<TX, TY>>
implements IRenderableSeries {
// ...
protected abstract IHitProvider<? super TRenderPassData> getHitProvider();
// ...
}
Derived classes in Java override getHitProvider as follows:
public class FastLineRenderableSeries<TX extends Comparable<TX>, TY extends Comparable<TY>> extends XyRenderableSeriesBase<TX, TY, LineRenderPassData> {
#Override
protected IHitProvider<? super LineRenderPassData> getHitProvider() {
return new CompositeHitProvider<>(
new PointMarkerHitProvider(),
new LineHitProvider());
}
}
In Xamarin.Android the binding is generated like this:
// Generated C# Binding in BaseRenderableSeries.cs
//
protected abstract global::Com.Scichart.Charting.Visuals.RenderableSeries.HitTest.IHitProvider RawHitProvider {
// Metadata.xml XPath method reference: path="/api/package[#name='com.scichart.charting.visuals.renderableSeries']/class[#name='BaseRenderableSeries']/method[#name='getHitProvider' and count(parameter)=0]"
[Register ("getHitProvider", "()Lcom/scichart/charting/visuals/renderableSeries/hitTest/IHitProvider;", "GetGetHitProviderHandler")] get;
}
Que? The property has been renamed from HitProvider to RawHitProvider. Derived classes of BaseRenderableSeries are trying to override HitProvider though and this is causing a build error.
// Generated bindings in FastLineRenderableSeries.cs
protected override unsafe global::Com.Scichart.Charting.Visuals.RenderableSeries.HitTest.IHitProvider HitProvider {
// Metadata.xml XPath method reference: path="/api/package[#name='com.scichart.charting.visuals.renderableSeries']/class[#name='FastLineRenderableSeries']/method[#name='getHitProvider' and count(parameter)=0]"
[Register ("getHitProvider", "()Lcom/scichart/charting/visuals/renderableSeries/hitTest/IHitProvider;", "GetGetHitProviderHandler")]
get {
// ...
}
}
}
FastLineRenderableSeries.HitProvider: no suitable method to override
Any idea why? What's Xamarin doing here and how can I prevent its craziness?

That's because generics aren't supported. Maybe there is a possible name conflict wich the generator tries to avoid.
Option a)
Try to change the name of the Property in the base class
<attr path="/api/package[#name='com.scichart.charting.visuals.renderableSeries']/class‌​[#name='BaseRenderableSeries']/method[#name='getHitProvider' and count(parameter)=0]"
name="managedName">HitProvider</attr>
Option b)
Change the name of the Property in the child classes
<attr path="/api/package[#name='com.scichart.charting.visuals.renderableSeries']/class[#name='FastLineRenderableSeries']/method[#name='getHitProvider' and count(parameter)=0]"
name="managedName">RawHitProvider</attr>

Related

How do I add my approval to the static class AssignmentMapType

I am new to Acumatica and need to add approvals to a custom module. Following the instruction found at https://stackoverflow.com/a/37331106/10006439 leads to adding a constant for the custom approval to the static class PX.Objects.EP.AssignmentMapType.
The code is located in PX.Objects\EP\DAC\AsssignmentMap.cs in the code repository, but it isn't part of the editable DAC definition when trying to customize the DAC inside of Acumatica.
Following the instructions, I need to add:
public class AssignmentMapTypeCS : Constant<string>
{
public AssignmentMapTypeCS() : base(typeof(STCSDocument).FullName) { }
}
What is the proper way to access AssignmentMapType to append my custom constant?
You put the constant anywhere you want it where publicly accessible.
In your namespace you can just create a static class like below.
public static class AssignmentMapType
{
...
public class AssignmentMapTypeCS : Constant<string>
{
public AssignmentMapTypeCS() : base(typeof(STCSDocument).FullName) { }
}
...
}

Create a Base TagHelper with no TargetElement

I'm creating a library of MVC6 TagHelpers for a large project.
I find myself writing certain functionality in these TagHelpers again and again.
I'd like to make a base TagHelper that all the others inherit from to remove all the duplicated code.
The issue is this - suppose I create a base TagHelper as below:
public class BaseTagHelper : TagHelper
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
//Some implementation...
}
}
Now, when I go to write a view, I will have intellisense suggesting the taghelper <base>.
Is there any way I can tell intellisense that this isn't a TagHelper I actually want to use, just a base class containing implementation common to other TagHelpers I've created?
Create it as an abstract class, see some examples in the official MVC Core repo like CacheTagHelperBase
public abstract class BaseTagHelper : TagHelper
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
//Some base implementation...
}
}

Windows Phone - Using generic class for PhoneApplicationPage

I have a Page which consist of AddPage.xaml and AddPage.xaml.cs. I want to create a generic class AddPage which extends from PhoneApplicationPage to outsource some repetitive code like Save or Cancel.
If I change the base class from PhoneApplicationPage to my new generic class, I get this error: Partial declarations of 'AddPage' must not specify different base classes.
To accomplish this you need to do the following.
First, create your base class
public class SaveCancelPhoneApplicationPage : PhoneApplicationPage
{
protected void Save() { ... }
protected void Cancel() { ... }
}
Then, your AddPage needs to be modified to inherit from the base class. The main places this is needed is within the code (AddPage.xaml.cs) AND within the xaml
Code:
public partial class AddPage : SaveCancelPhoneApplicationPage { ... }
Xaml:
<local:SaveCancelPhoneApplicationPage
x:Class="MyPhone.Namespace.AddPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyPhone.Namespace"
<!-- other xaml elements -->
</local:SaveCancelPhoneApplicationPage>
UPDATE: Info added based on comments
If you need to have generic like functionality and you must use the Page to do this (rather than a ViewModel) then you can still do this using generic methods
public abstract class SaveCancelPhoneApplicationPage : PhoneApplicationPage
{
protected override void OnNavigatedTo(blaa,blaa)
{
var obj = CreateMyObject();
obj.DoStuff();
}
// You should know what your objects are,
// don't make it usable by every phone dev out there
protected MyBaseObject MyObject { get; set; }
protected T GetMyObject<T>() where T : MyBaseObject
{
return MyObject as T;
}
}
public class AddPage : SaveCancelPhoneApplicationPage
{
public AddPage()
{
MyObject = new MyAddObject();
}
}
In order to outsource some functions you just declare some add class which does the common work. Having another page doesn't do that work.
public class Add
{
public bool SaveContent(string filename, string content)
{
....//some content
return true;
}
public string ViewContent(string filename)
{
string content="";
.....
return content;
}
}
Add this part of code where you thought it is redundant.
Add obj=new Add();
obj.SaveContent("myfile.txt","Hello.This is my content.");
string content("myfile.txt");
Tell me if this is what you intend or not.

Accessing ninject kernel in Application_Start

I am using Ninject and the MVC3 extension installed with nuget. My kernel setup code is in the App_Start/NinjectMVC3.cs file. Everything works great in controllers, but I can't figure out how to (properly) bind interfaces in the Global.asax.cs MvcApplication code.
I ended up using a hack (creating a public NinjectMVC3.GetKernel() method that returns bootstrap.kernel). However, that will be deprecated, and there must be a proper way to do this that I am not seeing.
Here is my code:
public class LogFilterAttribute : ActionFilterAttribute
{
private IReportingService ReportingService { get; set; }
public LogFilterAttribute( IReportingService reportingService )
{
this.ReportingService = reportingService;
}
...
}
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters( GlobalFilterCollection filters )
{
filters.Add( new HandleErrorAttribute() );
filters.Add( new LogFilterAttribute() );
}
...
protected void Application_Start()
{
...
RegisterGlobalFilters( GlobalFilters.Filters );
// NOTE hack:
var kernel = NinjectMVC3.GetKernel();
var logger = kernel.Get<ILogger>();
var bw = new BackgroundWork(logger);
Application["BackgroundWork"] = bw;
bw.Start();
}
}
There are two interfaces I am interested in. The first is just binding an object to a Global variable (the ILogger for the BackgroundWork).
And the second is for an ActionFilter. I read http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/, but I don't see how it plugs into the actual registration (filter.Add).
I don't want to use the Property Inject if I can avoid it.
Any thoughts on the proper way to do this?
Thanks
MVC 3 introduces the DependencyResolver which is populated into a singleton, and the Ninject extension supports it. You could use that in your MvcApplication class if you need it:
protected void Application_Start()
{
// ...
var logger = DependencyResolver.Current.GetService<ILogger>();
}
Now I should point out that it is unnecessary to do this with action filters. In Ninject.MVC3 you are supposed to use the BindFilter syntax, like so:
// Declare empty attribute
public class MyFilterAttribute : FilterAttribute { }
// Dependency module
public class MyModule : NinjectModule
{
public override void Load()
{
// Other bindings
// ...
this.BindFilter<MyActionFilter>(FilterScope.Action, 1)
.WhenControllerHas<MyFilterAttribute>();
}
}
Note that you have to use this because BindFilter is an extension method, and you also have to reference the Ninject.Web.Mvc.FilterBindingSyntax namespace.

Where to define AutoMapper mappings?

Where in my ASP.NET MVC application should I define my AutoMapper mappings?
Mapper.CreateMap<User, UserViewModel>();
Presently I am defining these in the constructor of a BaseController, which all my Controlllers derive from. Is this the best place?
I think it's kind of late to answer the question, but maybe someone can use my answer.
I use Ninject to resolve dependencies, so I've created Ninject Module for AutoMapper. Here is the code:
public class AutoMapperModule : NinjectModule
{
public override void Load()
{
Bind<IConfiguration>().ToMethod(context => Mapper.Configuration);
Bind<IMappingEngine>().ToMethod(context => Mapper.Engine);
SetupMappings(Kernel.Get<IConfiguration>());
Mapper.AssertConfigurationIsValid();
}
private static void SetupMappings(IConfiguration configuration)
{
IEnumerable<IViewModelMapping> mappings = typeof(IViewModelMapping).Assembly
.GetExportedTypes()
.Where(x => !x.IsAbstract &&
typeof(IViewModelMapping).IsAssignableFrom(x))
.Select(Activator.CreateInstance)
.Cast<IViewModelMapping>();
foreach (IViewModelMapping mapping in mappings)
mapping.Create(configuration);
}
}
As you can see on load it scans assembly for implementaion of IViewModelMapping and then runs Create method.
Here is the code of IViewModelMapping:
interface IViewModelMapping
{
void Create(IConfiguration configuration);
}
Typical implementation of IViewModelMapping looks like this:
public class RestaurantMap : IViewModelMapping
{
public void Create(IConfiguration configuration)
{
if (configuration == null)
throw new ArgumentNullException("configuration");
IMappingExpression<RestaurantViewModel, Restaurant> map =
configuration.CreateMap<RestaurantViewModel, Restaurant>();
// some code to set up proper mapping
map.ForMember(x => x.Categories, o => o.Ignore());
}
}
As mentioned in this answer, AutoMapper has now introduced configuration profiles to organise your mapping configuration.
So for example, you could define a class to set up your mapping configuration:
public class ProfileToOrganiseMappings : Profile
{
protected override void Configure()
{
Mapper.CreateMap<SourceModel, DestinationModel>();
//other mappings could be defined here
}
}
And then define a class to initialise the mappings:
public static class AutoMapperWebConfiguration
{
public static void Configure()
{
Mapper.Initialize(cfg =>
{
cfg.AddProfile(new ProfileToOrganiseMappings());
//other profiles could be registered here
});
}
}
And then finally, call that class in your global.asax Application_Start() to configure those mappings:
protected void Application_Start()
{
...
AutoMapperWebConfiguration.Configure();
}
The code you are referencing looks like AutoMapper, not StructureMap.
If you're using the static Mapper
method, configuration only needs to
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.
http://automapper.codeplex.com/wikipage?title=Getting%20Started&referringTitle=Home

Resources