Forum Cross Platform with Xamarin

XAM110: Code sharing in PCL with constructor injection

In XAM110 the following (pseudo?) code is shown:

public interface IDialer
{
    bool MakeCall(string number);   
}

public class Dialer
{
    public static Action<Dialer> Create;
    public bool MakeCall(string number) ...
    public Dialer(IDialer impl) { ... }
}

The only platform specific code shown is

Dialer.Create = () => new Dialer(new PhoneDialer.Droid());

Now I'm wondering what the rest of the code would be in a real implementation. How is MakeCall in Dialer implemented? The platform specific part can be something like

public class PhoneDialeriOS : IDialer
{
    public bool MakeCall(string number)
    {
        return UIApplication.SharedApplication.OpenUrl(new NSUrl("tel:" + number)); 
    }   
}

,but how is PhoneDialer constructed? A call to a method e.g. Droid() creates a platform specific instance? How?

Also how does the constructor public Dialer(IDialer impl) { } does look like, when Create doesn't return something?

Other samples from Xamarin are using DependencyService. Here are the implementations: iOS, Droid, WinPhone, UWP

I hope someone has some ideas about how the author thought about this.

Answers

  • anveanve DEMember ✭✭✭
    edited July 2016

    I think PhoneDialer.Droid() is only possible with a partial class, but here it is only for demonstration purposes without being real code. It should be PhoneDialerDroid or PhoneDialeriOS then. The rest could be something like this:

    // PCL
    public class Dialer
    {
        private IDialer dialer { get; set; }
    
        public static Action<Dialer> Create;
    
        public bool MakeCall(string number) {
            return this.dialer.MakeCall(number);
        }
    
        public Dialer(IDialer impl) {
            this.dialer = impl;
        }
    }
    
    // somewhere in the PCL
    Dialer dialer = Dialer.Create();
    
    // platform specific
    Dialer.Create = () => return new Dialer(new PhoneDialeriOS);
    

    But thats only a guess.

  • anveanve DEMember ✭✭✭

    This is wrong in my example

    // platform specific
    Dialer.Create = () => return new Dialer(new PhoneDialeriOS);
    

    and should be this

    // platform specific
    Dialer.Create = () => new Dialer(new PhoneDialeriOS);
    

    But the problematic code is this shown in the video:

    public static Action<Dialer> Create;

    I takes a parameter but doesn't return something. It is impossible to use that. That is an error. There are also some minor errors like typos, but there is no option to inform Xamarin University of the errors in their lectures.

    Nevertheless this could be a real implementation:

    // IDialer.cs (PCL)
    public interface IDialer
    {
        bool MakeCall(string number);
    }
    
    // Dialer.cs (PCL)
    public class Dialer
    {
        private IDialer dialer;
    
        public static Func<Dialer> Create;
        public bool MakeCall(string number)
        {
            return this.dialer.MakeCall(number);
        }
    
        public Dialer(IDialer impl)
        {
            this.dialer = impl;
        }
    }
    
    // App.cs (PCL)
    
    public class App : Application
    {
        private Dialer dialer;
    
        public App()
        {
            this.dialer = Dialer.Create();
    
            Button callButton = new Button
            {
                Text = "Make call"
            };
    
            callButton.Clicked += CallButton_Clicked;
    
            MainPage = new ContentPage
            {
                Content = new StackLayout
                {
                    VerticalOptions = LayoutOptions.Center,
                    Children = {
                        callButton,
                    }
                }
            };
        }
    
        private void CallButton_Clicked(object sender, EventArgs e)
        {
            this.dialer.MakeCall("1234567890");
        }
    }
    
    // AppDelegate.cs (iOS)
    
    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            Dialer.Create = () => new Dialer(new PhoneDialeriOS());
    
            global::Xamarin.Forms.Forms.Init();
            LoadApplication(new App());
    
            return base.FinishedLaunching(app, options);
        }
    }
    
    // PhoneDialeriOS.cs (iOS)
    public class PhoneDialeriOS : IDialer
    {
        public bool MakeCall(string number)
        {
            return UIApplication.SharedApplication.OpenUrl(new NSUrl("tel:" + number));
        }
    }
    

    Why it doesn't use a static factory? Why there are two options for creating an instance? Nobody knows ...

Sign In or Register to comment.