locked
XAM110: Code sharing in PCL with constructor injection RRS feed

  • Question

  • User67478 posted

    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.

    Monday, July 4, 2016 1:55 PM

All replies

  • User67478 posted

    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.

    Monday, July 25, 2016 11:08 AM
  • User67478 posted

    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 ...

    Tuesday, August 2, 2016 1:08 PM