I have platform specific sdks to be implemented and using Dependency Service for this purpose.
Upon a button click, I want to invoke the native sdks, but not sure how this can be done. Here is what I have tried.
Main Page
private async void ButtonClickMethod(object sender, EventArgs e, string name)
{
// InterfaceDemo if = DependencyService.Get<InterfaceDemo>().GetName() ///Tried this, but fails.
DependencyService.Get<InterfaceDemo>().GetName(); ///How can this be invoked on button click
}
Interface class:
namespace Demo
{
public interface InterfaceDemo
{
void GetName();
}
}
Platform Specific code:
namespace Demo.Droid
{
public partial class Demo : InterfaceDemo
{
public async void GetName()
{
/// code
}
}
}
What you have done is correct but you have missed one very important line of code i.e. registering the Dependency in your native assembly.
So the updated Platform Specific Code will have the following attribute:-
[assembly: Xamarin.Forms.Dependency(typeof(Demo))]
namespace Demo.Droid
{
public partial class Demo : InterfaceDemo
{
public async void GetName()
{
/// code
}
}
}
Related
I am not sure how to decide about how to refactor some production code. This code works as select records top 1 from db and decided to column containing value under the below.
switch(column_value):
case send_email:
send_email.DoIt();
case enable_somexx:
enable_somexx.DoIt();
case response_email:
response_email.DoIt();
Showing the below examples, there are created classes for every events (records) including a DoIt() method(SendMail, DecideMail, ResponseMail, MailXXX, enable_somexx). The classes include 3 subfolders actions named action, decision, response (actually these classes irrelevant which other because code select top 1 record)
I'm thinking of refactoring this code logic like this:
Create base class named Behaviour
other 3 main classes will inherit from this base class
Code:
public abstract Behaviour
{
public virtual void DoIt(string type) {
}
}
--Also another classes Decision, Response will inherit from Behaviour.
public class Action : Behaviour
{
override void DoIt(string type) {
}
}
public class Email : Action
{
override void DoIt(string type)
{
if(type == SEND)
call_sendmethod
else if(xxx_operation_about_mail)
call_xxx_operation_about_mail
}
}
But I cannot handle (actually I don't like my solution because I don't want to create same class every operations like EmailAction, EmailResponse, EmailDecision or another operations)
If you make this code block refactoring, how would you do it?
Thank you.
Using your idea of refactoring ... this is how I would code it:
Here is an outline:
Create an abstract class for Behavior
Create an action class which inherits Behavior
Then you can code like this to trigger desire "action".
Notice how I override the "Send" behavior to customize it to "special sent".
Here is the fiddle: https://dotnetfiddle.net/m3tjWl
Blockquote
public class Program : Action
{
public static void Main()
{
Console.WriteLine("Hello World");
var command = Console.ReadLine();
//trigger send from Action class
Action x = new Action();
x.DoIt(command);
//trigger send from behavior class
//the lines below are added to show how you can still access the parent behavior, remove or use where appropriate
Behaviour y = x;
y.Send();
}
}
public abstract class Behaviour
{
public virtual void Send()
{
Console.WriteLine("sent");
}
public virtual void EnableX()
{
Console.WriteLine("enabled");
}
public virtual void Reply()
{
Console.WriteLine("replied");
}
public abstract void DoIt(string type);
}
public class Action : Behaviour
{
public override void DoIt(string type)
{
if(type.ToUpper() == "SEND")
this.Send();
else if (type.ToUpper() == "ENABLEX")
this.EnableX();
else if (type.ToUpper() == "REPLY")
this.Reply();
else
Console.WriteLine("Unknown Command");
}
new public void Send()
{
Console.WriteLine("Special Sent");
}
}
I have a Xamarin-Objective C binding project (see here: https://github.com/bbhsu2/XamarinAdMarvelBinding). Fundamentally, it works and I can load clickable ads.
So I implement the AdMarvelDelegate interface on my ViewController class, but important implemented methods are not getting called:
public class CategoryViewController : UITableViewController, IAdMarvelDelegate
{
/*Initializing stuff*/
public void GetAdSucceeded() //not called
{
Console.WriteLine("succeeded!");
}
public void GetAdFailed() //not called
{
Console.WriteLine("failed!");
AppDelegate.Shared.AddAdBanner();
}
}
Does anyone have any suggestions on why GetAdSucceeded and GetAdFailed are not called? In the binding project I have:
[Export("getAdSucceeded")]
void GetAdSucceeded();
[Export("getAdFailed")]
void GetAdFailed();
which I believe are correct
If the corresponding members in AdMarvelDelegate are optional (i.e. they don't have the [Abstract] attribute in the binding), you'll need the [Export] attribute on those methods:
public class CategoryViewController : UITableViewController, IAdMarvelDelegate
{
[Export ("getAdSucceeded")]
public void GetAdSucceeded()
{
Console.WriteLine("succeeded!");
}
[Export("getAdFailed")]
public void GetAdFailed()
{
Console.WriteLine("failed!");
AppDelegate.Shared.AddAdBanner();
}
}
I'm using a custom application class for storing my global variables but i don't seem to be able to get it to work.
here is my class :
#if DEBUG
[assembly: Application(Debuggable = true)]
#else
[assembly: Application(Debuggable=false)]
#endif
internal class MyApp : Application
{
private Customer loginedCustomer;
private List<string> sefareshItems;
public Boolean isOnline { set; get; }
public MyApp(IntPtr handle, JniHandleOwnership ownerShip) : base(handle, ownerShip)
{
}
public override void OnCreate()
{
// If OnCreate is overridden, the overridden c'tor will also be called.
base.OnCreate();
}
public void SetLCustomer(Customer customer)
{
loginedCustomer = customer;
}
public Customer GetLCustomer()
{
return loginedCustomer;
}
public void SetItems(List<string> items)
{
sefareshItems = items;
}
public List<string> GetItems()
{
return sefareshItems;
}
}
and since i could find any documentation about using such class and by looking at the java examples both of these code gives me the "unable to cast from source to destination" exception
MyApp m = (MyApp)Application;
and
Myapp m=(MyApp)ApplicationContext;
could you help me figure this out?
and i have another question.is it a good practice to get or set variables using methods or using a public static one?
thank you
Application is a class definition.
You will need an instance of Application to cast as MyApp.
Make MyApp a static Class.
Make your method's static methods.
Then you can simply access Replace all references to Application with MyApp, and use it that way.
I have a method that does some stuff that takes a while and posts progress/status messages back. The method used to be the Main() static method in my console Program class. Later, I decided to move the functionality into a shared library assembly, so that the same functionality could be accessed by a new web api project, so a different user interface with different mechanisms for stdio.
What is a good design pattern to replace all my Console.Writeline() calls in the moved method?
I'm thinking along the lines of adding an observable collection (of strings) to store the messages and then getting any calling assemblies to subscribe to changes on the collection and implement their own ui mechanisms for displaying messages back to the user.
Is this reasonable or is this reinventing the wheel? Is there already a purpose built method in the framework to handle a scenario like this?
Edit:
Thanks to #astef, I implemented it like so:
public interface IMessageObserver
{
void Notify(string message);
void Notify(string format, params object[] args);
}
public class ConsoleMessageObserver : IMessageObserver
{
public void Notify(string message)
{
Console.WriteLine(message);
}
public void Notify(string format, params object[] args)
{
Console.WriteLine(format, args);
}
}
class Program
{
static void Main()
{
Library.LongRunningMethod(new ConsoleMessageObserver());
}
}
static class Library
{
public static void LongRunningMethod(IMessageObserver observer)
{
observer.Notify("Some progress happened...");
}
}
If you need someone to handle your progress messages, just define it:
public interface IProgressObserver
{
void NotifyProgress(double done);
}
And use:
public void YourLongRunningMethod(IProgressObserver progressObserver)
{
// ...
progressObserver.NotifyProgress(1d);
}
Now you can be more specific on who will actually handle this messages. For example:
public class ConsoleProgressObserver : IProgressObserver
{
public void NotifyProgress(double done)
{
Console.WriteLine("Progress: {0:0.00}%", done * 100);
}
}
Here's one that was used in Windows 98 system ;)
public class StuckingProgressObserver : IProgressObserver
{
private const double stucksAfter = 0.95;
private readonly IProgressObserver wrapee;
public StuckingProgressObserver(IProgressObserver wrapee)
{
this.wrapee = wrapee;
}
public void NotifyProgress(double done)
{
if (done < stucksAfter)
{
wrapee.NotifyProgress(done);
}
}
}
Using an event, like #astef suggests is a good idea, but their code isn't idiomatic C#. .NET supports delegates directly, so there is no need for a one method interface.
In C# we'd define a class ProgressChangedEventArgs : EventArgs and then add an EventHandler<ProgressChangedEventArgs> ProgressChanged to the class that generates the event.
In fact the framework already includes those in the System.ComponentModel namespace.
I searched some fora and topics to look for the answer but I'm not able to find the solution for my problem. I'll post the code:
namespace Configurator
{
public partial class Dialog : Form
{
private DataStorage dataStorage = null;
public Dialog
{
InitializeComponent();
}
public void setDataStorage(ref DataStorage ds)
{
this.dataStorage = ds;
}
}
}
And it's being used in this class:
namespace Configurator
{
public partial class MainView : Form
{
private DataStorage dataStorage = new DataStorage();
private Dialog DialogBox = new Dialog();
public MainView
{
InitializeComponent();
}
private void newObjectButton_Click(object sender, EventArgs e)
{
DialogBox.Show();
DialogBox.setDataStorage(ref dataStorage);
}
}
}
This is the error:
Inconsistent accessibility: parameter type 'ref Configurator.DataStorage' is less accessible than method Configurator.Dialog.setDataStorage(ref Configurator.DataStorage)
Mark your class DataStorage with public and your error will go away :)
Your class Dialog is public. Your method setDataStorage is also public. This makes this method visible to all other assemblies. But how can other assemblies use that method if they do not have access to the parameter type DataStorage because that one is not visible (probably because it is marked private or internal.)