In my previous article about Xamarin, I’ve explained a way to access user’s contact by using the ManagedQuery API. Even if the code is working fine, you may think that it can be a bit “hard” to understand, when the only goal is to query the contacts.

Today, I’ll talk about Xamarin.Mobile, a library that exposes some APIs to access user’s contacts, user’s position and to allow you to, easily, take a picture in your application. The interesting point here is the fact that the API is available for iOS, Android and Windows Phone.

To use Xamarin.Mobile, you need to download the binaries. Thanks to the Components Store available (something that’s a bit similar to Nuget), you can get them easily:

image image

After you hit the “Add to App” button, the component is downloaded and the reference is added to your project:

image image

Once the reference is added, the first step is to add the following “using”:

using Xamarin.Contacts;

Now, by using the AddressBook class, we are able to access to the user’s contacts and we can use LINQ, which provides a more easier and comfortable syntax:

var addressBook = new AddressBook(this);
if (!await addressBook.RequestPermission())
{
    // We don't have the permission to access user's contacts: check if the READ_CONTACTS has been set
}
else
{
    var companyContacts = addressBook.Where(c => c.Organizations.Any(o => o.Name == "Infinite Square"));
    if (companyContacts.Any())
    {
        foreach (var contact in companyContacts)
        {
            var lastName = contact.LastName;
            var firstName = contact.FirstName;
            var thumbnailBitmap = contact.GetThumbnail();
        }
    }
}

As you can see, the code is really easy to understand and maintainable!

 

If you want to know more about Xamarin.Mobile (or just check how does it work), feel free to go to Github, where you’ll be able to find the sources: https://github.com/xamarin/Xamarin.Mobile

 

Happy (Xamarin) coding!

The videos of the sessions I’ve animated during the last TechDays 2012 in Paris, France have been published and are now available:

  1. MVVM de A à Z
  2. WPF 4.5: Quoi de neuf pour les développeurs ?

The last session (“Améliorez votre productivité XAML en entreprise”) has not been published but I’ll update my post as soon as  you’ll be able to see it.

 

Happy coding!

As I’ve explained before, I’ll be presenting 3 sessions during the next TechDays in France.

One of the session is entitled “Améliorer votre productivité XAML en entreprise” and we are currently working on it. If you plan to attend to our session (or to TechDays), we want to learn from you: we give you the opportunity to let us know what you want to see in the session !

If you have any particular needs or if you have some subjects that you want to see covered in the session, let me know (in a comment) and we’ll try do our best !

Thanks and don’t forget: if you plan to come in TechDays 2012, feel free to come to see me.

 

Happy coding!

Next month (7, 8 and 9 February), Microsoft France will organize the most important IT event of the year in the country: the Microsoft TechDays 2012 !

During the event, I’ll be presenting 3 sessions:

  1. WPF 4.5 : Quoi de neuf pour les développeurs ? (RDA105)
  2. MVVM de A à Z (RDA106)
  3. Améliorer votre productivité XAML en entreprise ! (RDA201)

If you are in Paris and attending the event, feel free to come to meet me and talk about WPF, Silverlight, Windows Phone and other XAML stuff !

 

See you there!

Prism is a well-know framework to develop applications that support modularity, navigation, communication between loosely coupled components and more !

Each module is loaded automatically (OnDemand property of Module attribute set to false) or on demand (OnDemand set to true) but in all case, you can’t define in which order the modules are loaded. By default, they are loaded by using their name and you don’t have any way to change that.

In my case, I wanted to be able to load my modules in specific order. So, after taking a look on Internet, I’ve found this post on StackOverFlow: http://stackoverflow.com/questions/1296642/how-to-control-the-order-of-module-initialization-in-prism

The code work fine except for modules that are asked to be loaded on demand. So I needed to find a way to be able to specify the loading order of each module, even if they have to be started on demand) and, for that, I’ve been inspired by the previous code.

Indeed, I first create the Priority attribute:

/// <summary>
/// Allows the order of module loading to be controlled.  Where dependencies
/// allow, module loading order will be controlled by relative values of priority
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class PriorityAttribute : Attribute
{
    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="priority">the priority to assign</param>
    public PriorityAttribute(int priority)
    {
        this.Priority = priority;
    }

    /// <summary>
    /// Gets or sets the priority of the module.
    /// </summary>
    /// <value>The priority of the module.</value>
    public int Priority { get; private set; }
}

Then, I created a dedicated ModuleCatalog, inspired by the PrioritizedDirectoryCatalog (from the post of StackOverFlow) and the DirectoryModuleCatalog (from the Prism’s sources):

public class PrioritizedDirectoryModuleCatalog : DirectoryModuleCatalog
{
    protected override void InnerLoad()
    {
        if (string.IsNullOrEmpty(this.ModulePath))
            throw new InvalidOperationException("The ModulePath cannot contain a null value or be empty.");

        if (!Directory.Exists(this.ModulePath))
            throw new InvalidOperationException(
                string.Format(CultureInfo.CurrentCulture, "Directory {0} was not found.", this.ModulePath));

        AppDomain childDomain = this.BuildChildDomain(AppDomain.CurrentDomain);

        try
        {
            List<string> loadedAssemblies = new List<string>();

            var assemblies = (
                                 from Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()
                                 where !(assembly is System.Reflection.Emit.AssemblyBuilder)
                                    && assembly.GetType().FullName != "System.Reflection.Emit.InternalAssemblyBuilder"
                                    && !String.IsNullOrEmpty(assembly.Location)
                                 select assembly.Location
                             );

            loadedAssemblies.AddRange(assemblies);

            Type loaderType = typeof(ModulePriorityLoader);

            if (loaderType.Assembly != null)
            {
                var loader =
                    (ModulePriorityLoader)
                    childDomain.CreateInstanceFrom(loaderType.Assembly.Location, loaderType.FullName).Unwrap();
                loader.LoadAssemblies(loadedAssemblies);
                this.Items.AddRange(this.Sort(loader.GetModuleInfos(this.ModulePath)));
            }
        }
        finally
        {
            AppDomain.Unload(childDomain);
        }
    }

    /// <summary>
    /// Sort modules according to dependencies and Priority
    /// </summary>
    /// <param name="modules">modules to sort</param>
    /// <returns>sorted modules</returns>
    protected override IEnumerable<ModuleInfo> Sort(IEnumerable<ModuleInfo> modules)
    {
        Dictionary<string, int> priorities = GetPriorities(modules);

        //call the base sort since it resolves dependencies, then re-sort 
        var result = new List<ModuleInfo>(base.Sort(modules));
        result.Sort((x, y) =>
        {
            string xModuleName = x.ModuleName;
            string yModuleName = y.ModuleName;

            //if one depends on other then non-dependent must come first
            //otherwise base on priority
            if (x.DependsOn.Contains(yModuleName))
                return 1; //x after y
            else if (y.DependsOn.Contains(xModuleName))
                return -1; //y after x
            else
                return priorities[xModuleName].CompareTo(priorities[yModuleName]);
        });

        return result;
    }

    /// <summary>
    /// Get the priorities
    /// </summary>
    /// <param name="modules"></param>
    /// <returns></returns>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFrom")]
    public Dictionary<string, int> GetPriorities(IEnumerable<ModuleInfo> modules)
    {
        //retrieve the priorities of each module, so that we can use them to override the 
        //sorting - but only so far as we don't mess up the dependencies
        var priorities = new Dictionary<string, int>();
        var assemblies = new Dictionary<string, Assembly>();

        foreach (ModuleInfo module in modules)
        {
            if (!assemblies.ContainsKey(module.Ref))
            {
                //LoadFrom should generally be avoided appently due to unexpected side effects,
                //but since we are doing all this in a separate AppDomain which is discarded
                //this needn't worry us
                assemblies.Add(module.Ref, Assembly.LoadFrom(module.Ref));
            }

            Type type = assemblies[module.Ref].GetExportedTypes()
                .Where(t => t.AssemblyQualifiedName.Equals(module.ModuleType, StringComparison.Ordinal))
                .First();

            var priorityAttribute =
                CustomAttributeData.GetCustomAttributes(type).FirstOrDefault(
                    cad => cad.Constructor.DeclaringType.FullName == typeof(PriorityAttribute).FullName);

            int priority;
            if (priorityAttribute != null)
            {
                priority = (int)priorityAttribute.ConstructorArguments[0].Value;
            }
            else
            {
                priority = 0;
            }

            priorities.Add(module.ModuleName, priority);
        }

        return priorities;
    }

    /// <summary>
    /// Local class to load assemblies into different appdomain which is then discarded
    /// </summary>
    private class ModulePriorityLoader : MarshalByRefObject
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        internal void LoadAssemblies(IEnumerable<string> assemblies)
        {
            foreach (string assemblyPath in assemblies)
            {
                try
                {
                    Assembly.ReflectionOnlyLoadFrom(assemblyPath);
                }
                catch (FileNotFoundException)
                {
                    // Continue loading assemblies even if an assembly can not be loaded in the new AppDomain
                }
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        internal ModuleInfo[] GetModuleInfos(string path)
        {
            DirectoryInfo directory = new DirectoryInfo(path);

            ResolveEventHandler resolveEventHandler =
                delegate(object sender, ResolveEventArgs args) { return OnReflectionOnlyResolve(args, directory); };

            AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += resolveEventHandler;

            Assembly moduleReflectionOnlyAssembly =
                AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies().First(
                    asm => asm.FullName == typeof(IModule).Assembly.FullName);

            Type IModuleType = moduleReflectionOnlyAssembly.GetType(typeof(IModule).FullName);

            IEnumerable<ModuleInfo> modules = GetNotAllreadyLoadedModuleInfos(directory, IModuleType);

            var array = modules.ToArray();
            AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= resolveEventHandler;

            return array;
        }

        private static IEnumerable<ModuleInfo> GetNotAllreadyLoadedModuleInfos(DirectoryInfo directory, Type IModuleType)
        {
            List<FileInfo> validAssemblies = new List<FileInfo>();
            Assembly[] alreadyLoadedAssemblies = AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies();

            var fileInfos = directory.GetFiles("*.dll")
                .Where(file => alreadyLoadedAssemblies
                                   .FirstOrDefault(
                                   assembly =>
                                   String.Compare(Path.GetFileName(assembly.Location), file.Name,
                                                  StringComparison.OrdinalIgnoreCase) == 0) == null);

            foreach (FileInfo fileInfo in fileInfos)
            {
                Assembly assembly = null;
                try
                {
                    assembly = Assembly.ReflectionOnlyLoadFrom(fileInfo.FullName);
                    validAssemblies.Add(fileInfo);
                }
                catch (BadImageFormatException)
                {
                    // skip non-.NET Dlls
                }
            }

            return validAssemblies.SelectMany(file => Assembly.ReflectionOnlyLoadFrom(file.FullName)
                                        .GetExportedTypes()
                                        .Where(IModuleType.IsAssignableFrom)
                                        .Where(t => t != IModuleType)
                                        .Where(t => !t.IsAbstract)
                                        .Select(type => CreateModuleInfo(type)));
        }

        private static Assembly OnReflectionOnlyResolve(ResolveEventArgs args, DirectoryInfo directory)
        {
            Assembly loadedAssembly = AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies().FirstOrDefault(
                asm => string.Equals(asm.FullName, args.Name, StringComparison.OrdinalIgnoreCase));
            if (loadedAssembly != null)
            {
                return loadedAssembly;
            }

            AssemblyName assemblyName = new AssemblyName(args.Name);
            string dependentAssemblyFilename = Path.Combine(directory.FullName, assemblyName.Name + ".dll");
            if (File.Exists(dependentAssemblyFilename))
            {
                return Assembly.ReflectionOnlyLoadFrom(dependentAssemblyFilename);
            }
            return Assembly.ReflectionOnlyLoad(args.Name);
        }

        private static ModuleInfo CreateModuleInfo(Type type)
        {
            string moduleName = type.Name;
            List<string> dependsOn = new List<string>();
            bool onDemand = false;
            var moduleAttribute =
                CustomAttributeData.GetCustomAttributes(type).FirstOrDefault(
                    cad => cad.Constructor.DeclaringType.FullName == typeof(ModuleAttribute).FullName);

            if (moduleAttribute != null)
            {
                foreach (CustomAttributeNamedArgument argument in moduleAttribute.NamedArguments)
                {
                    string argumentName = argument.MemberInfo.Name;
                    switch (argumentName)
                    {
                        case "ModuleName":
                            moduleName = (string)argument.TypedValue.Value;
                            break;

                        case "OnDemand":
                            onDemand = (bool)argument.TypedValue.Value;
                            break;

                        case "StartupLoaded":
                            onDemand = !((bool)argument.TypedValue.Value);
                            break;
                    }
                }
            }

            var moduleDependencyAttributes =
                CustomAttributeData.GetCustomAttributes(type).Where(
                    cad => cad.Constructor.DeclaringType.FullName == typeof(ModuleDependencyAttribute).FullName);

            foreach (CustomAttributeData cad in moduleDependencyAttributes)
            {
                dependsOn.Add((string)cad.ConstructorArguments[0].Value);
            }

            ModuleInfo moduleInfo = new ModuleInfo(moduleName, type.AssemblyQualifiedName)
            {
                InitializationMode =
                    onDemand
                        ? InitializationMode.OnDemand
                        : InitializationMode.WhenAvailable,
                Ref = type.Assembly.CodeBase,
            };
            moduleInfo.DependsOn.AddRange(dependsOn);

            return moduleInfo;
        }
    }
}

Now, in your Bootstrapper, you simply have to use your new ModuleCatalog:

protected override IModuleCatalog CreateModuleCatalog()
{
    return new PrioritizedDirectoryModuleCatalog { ModulePath = ".\Modules" };
}

Then, decorate each of your module with this new attribute:

[Module(ModuleName = "RootModule", OnDemand = false)]
[Priority(-1)]
public class RootModule : IModule

[Module(ModuleName = "ModuleA", OnDemand = true)]
[Priority(1)]
public class ModuleAModule : IModule

All that’s all ! If you enumerate all the modules, you will be able to see that they are ordered as you define it: RootModule will be the first, then, ModuleA (even if the sort on the name will produce a different result):

[Dependency]
public IModuleCatalog ModuleCatalog { get; set; }

[Dependency]
public IModuleManager ModuleManager { get; set; }

foreach (var module in this.ModuleCatalog.Modules.Where(m => m.InitializationMode != InitializationMode.WhenAvailable))
{
    this.ModuleManager.LoadModule(module.ModuleName);
}

 

Happy coding!

With one of my colleague (and friend), Jonathan ANTOINE, we have just release a new book, in French, on the MVVM Pattern. It targets WPF, Silverlight and Windows Phone technologies.

clip_image001[6]

Its title is “MVVM, De la découverte à la maitrise” and aims to help developers to understand all the principles of the pattern. It is available as an eBook from our publisher: http://www.digitbooks.fr/catalogue/mvvm-antoine-lebrun.html but you can also order it as a paper book !

We hope you’ll appreciate it! Oh and, by the way, don’t hesitate to share the information if you like it!

Thanks and happy coding !

Bonjour à tous,

J’y pensais depuis un moment, c’est maintenant chose faîte ! J’ai décidé de changer de plateforme de blog pour me lancer dans ma “propre” aventure.

Les activités prévues au programme seront les mêmes que sur mon précédent blog à savoir WPF, Silverlight,  Windows Phone, etc. mais en essayant de varier les plaisirs de temps en temps et surtout, en essayant de retrouver une activité un peu plus dense.

Je tiens à remercier la communauté de CodeS-SourceS, et notamment Nix et Cyril, pour m’avoir hébergé durant toutes ces années !

Vous remarqerez que le design de ce blog n’est, pour le moment, pas tout à fait abouti: j’espère que cela changera rapidement (si d’ailleurs vous souhaitez me filer un coup de main sur la partie  design/logo, n’hésitez pas à me le faire savoir, je risque d’en avoir besoin !)

 

A bientôt pour la suite !