locked
How to implement the same interface with several WinRT components

    Question

  • I worked with COM from 1995 until late 2002 when .NET appeared. One of the main power of COM is the ability to expose the same interface with different components and load the desired one when needed.

    I have tried a very trivial thing:

    Implement the same IPerson interface with 2 different WinRT components. First I declared the IPerson in the namespace of my first Person implementation that I called WinRTCompV2. This compile and works.

    Then I created a second WinRT component in a second namespace that I called WinRTCompV3 and this new Person inherits from the same IPerson interface defined in WinRTCompV2

    Basically I have:

    namespace WinRTComp2
    {

    public interface class IPerson
    {
    property String^ Name;
    property String^ Surname;
    };
    }

    then I implemented the class person

    namespace WinRTComp2
    {
    public ref class Person sealed : IPerson
    {
    // Implementation code there
    };
    }

    I compile and use a unit test in C#, it works fine.

    Then I created a second implementation of Person in a different namespace 

    using namespace WinRTComp2;

    namespace WinRTComp3
    {
    public ref class Person sealed : IPerson
    {
    // Implementation code there
    };
    }

    This compiles fine in C++ but when I compile the unit test in C#, I get the following errors regarding the .winmd file.

    Error 9 The .winmd file 'WinRTCompV2.winmd' contains type 'WinRTCompV3.__IPersonFactory' outside its root namespace 'WinRTCompV2'. Make sure that all public types appear under a common root namespace that matches the output file name. UnitTestWinRTComp

    Error 8 The .winmd file 'WinRTCompV2.winmd' contains type 'WinRTCompV3.__IPersonPublicNonVirtuals' outside its root namespace 'WinRTCompV2'. Make sure that all public types appear under a common root namespace that matches the output file name. UnitTestWinRTComp


    I have searched on other forum and I cannot find any information regarding this issue or even someone who is trying to do something so simple than implementing the same interface with different components!

    As it is not a secret that WinRT is a modern version of COM I would expect that it is possible to do everything that was possible with COM plus a lot of new things. However my first trials give me the impression that this is the opposite which is happening.

    Could any one explain how such a trivial pattern can be achieved with C++/CX?

    Thanks for your help.

    O. Rouit


    Software Architect, Advanced IT Tokens Team - Gemalto

    Friday, November 23, 2012 3:07 PM

Answers

  • After some thinking and a new trial I could implement the same interface with 2 components in the same DLL.

    The following limitation applies:

    ALL the components and the interface must be in the SAME namespace.

    Ex:

    namespace Test
    {
        public interface class ICitizen
        {
        };

        public ref class FrenchCitizen sealed : ICitizen
        {
        };

        public ref class USCitizen sealed : ICitizen
        {
        };
    }

    This construction works!

    Hope it will help someone!

    O. ROUIT

        


    Software Architect, Advanced IT Tokens Team - Gemalto

    • Marked as answer by orouit Saturday, December 01, 2012 11:02 AM
    Wednesday, November 28, 2012 4:26 PM
  • Thanks for reporting the issue. I have escalated this internally. In the meantime, you can work around the issue by implementing the interface in a Windows Store project, instead of the Windows Runtime Component.

    Cheers.


    Helge Mahrt - Microsoft Developer Support Engineer - If my reply answers your question, please mark this post as answered.

    • Marked as answer by orouit Saturday, December 01, 2012 11:02 AM
    Thursday, November 29, 2012 5:33 PM

All replies

  • I finally managed to do what I wanted. The current solution I found is to create the WinRTCompV2 namespace of components in a given DLL, then I created a new set of components with the namespace WinRTCompV3 in another DLL, then I referenced the WinRTCompV2 DLL my second DLL and I can use the interfaces that were defined in WinRTCompV2 and give a different implementation.

    It looks like there is a rule (COM is usually full of rules) that wants that only one namespace can be exposed from the same DLL. There might be a trick expose multiple namespace and cross reference them but I haven't managed to find that.

    I'll appreciate if someone of Microsoft could direct me to some reference documentation that explain all the new rules of this modern COM!!!

    I hhad a look at somebooks but frankly speaking their content is really poor and superficial. None of them illustrate this so simple pattern of implementing one interface with different WinRT components. 

    Thanks

    O. ROUIT


    Software Architect, Advanced IT Tokens Team - Gemalto

    Friday, November 23, 2012 4:39 PM
  • In my discovery of WinRT I tried something that I thought would be totally natural. 

    Create a WinRT component in C++/CX, implement it in C++ and then import the reference in a C# WinRT component and implement the same interface in C#

    Everything looks fine until compile time. I then get a mysterious error that doesn't really make sense to me, because it sounds like internal issue.

    Here is an extract of the code:

    This is the declaration of the interface in C++

    /**
    @brief Represents a simple person object
    */
    public interface class IPerson : ISaveable
    {
    /**
    Name property for the person
    */
    property String^ Name;

    /**
    Name property for the person
    */
    property String^ Surname;
    };

    This is the implementation in C#

        public sealed class Person : IPerson
        {
            #region Fields

            private string name;
            private string surname;

            #endregion

            #region Constructors

            public Person()
            {
            }

            public Person(string name, string surname)
            {
                this.surname = surname;
            }

            #endregion

            public string Name
            {
                get;
                set;
            }

            public string Surname
            {
                get
                {
                    return surname;
                }
                set
                {
                    surname = value;
                }
            }

            public bool CanSave()
            {
                return name.Length > 0 && surname.Length > 0;
            }
        }

    I didn't include the namespace but they are all fine. C# imports properly the definition of the interface and generates the skeleton of its implementation.

    But at compile time I get the following errors.

    Error 1 Method 'WinRTCompNet.Person.WinRTCompV2.IPerson.set_Name(System.String)' has a parameter named '' whereas the corresponding parameter in the implemented interface method 'WinRTCompV2.IPerson.Name.set(System.String)' is named '__param0'. Please make sure that the names are identical. C:\Users\Olivier\documents\visual studio 2012\Projects\TestWinRT\WinRTCompNet\Person.cs 11 25 WinRTCompNet

    Error 2 Method 'WinRTCompNet.Person.WinRTCompV2.IPerson.set_Surname(System.String)' has a parameter named '' whereas the corresponding parameter in the implemented interface method 'WinRTCompV2.IPerson.Surname.set(System.String)' is named '__param0'. Please make sure that the names are identical. C:\Users\Olivier\documents\visual studio 2012\Projects\TestWinRT\WinRTCompNet\Person.cs 11 25 WinRTCompNet

    Is there anything I missed somewhere or could there be a problem with the C# compiler?

    I post this issue here because it's partly C++/CX and C#. Feel free to transmit this issue to the correct person...


    Software Architect, Advanced IT Tokens Team - Gemalto

    • Merged by Jesse Jiang Monday, November 26, 2012 9:10 AM Same issue
    Saturday, November 24, 2012 6:13 AM
  • Hello,
     
    Thanks for your feedback, I will involve more experts to investigate it.
     
    Best regards,
    Jesse

    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us

    Tuesday, November 27, 2012 3:15 AM
  • Hello orouit,

    To be able to analyze the issue, please send me your solution to hmahrt at microsoft.

    Cheers.


    Helge Mahrt - Microsoft Developer Support Engineer - If my reply answers your question, please mark this post as answered.

    Tuesday, November 27, 2012 3:33 PM
  • Ok I'll pack a solution test  and send it to you by the end of the day.

    As I see I can't attach a solution in this post.

    Thks for your help

    O. Rouit


    Software Architect, Advanced IT Tokens Team - Gemalto


    Tuesday, November 27, 2012 11:47 PM
  • Yes, please send it to my email address. If the attachment is too big, please let me know and I will provide you with other means to transfer the files to me.

    Cheers.


    Helge Mahrt - Microsoft Developer Support Engineer - If my reply answers your question, please mark this post as answered.

    Wednesday, November 28, 2012 8:05 AM
  • I'm installing the VS Update 1, then I try again and if it still doesn't work I send the solution. It's just a few Kbytes

    O. Rouit


    Software Architect, Advanced IT Tokens Team - Gemalto

    Wednesday, November 28, 2012 2:03 PM
  • After some thinking and a new trial I could implement the same interface with 2 components in the same DLL.

    The following limitation applies:

    ALL the components and the interface must be in the SAME namespace.

    Ex:

    namespace Test
    {
        public interface class ICitizen
        {
        };

        public ref class FrenchCitizen sealed : ICitizen
        {
        };

        public ref class USCitizen sealed : ICitizen
        {
        };
    }

    This construction works!

    Hope it will help someone!

    O. ROUIT

        


    Software Architect, Advanced IT Tokens Team - Gemalto

    • Marked as answer by orouit Saturday, December 01, 2012 11:02 AM
    Wednesday, November 28, 2012 4:26 PM
  • Thanks for reporting the issue. I have escalated this internally. In the meantime, you can work around the issue by implementing the interface in a Windows Store project, instead of the Windows Runtime Component.

    Cheers.


    Helge Mahrt - Microsoft Developer Support Engineer - If my reply answers your question, please mark this post as answered.

    • Marked as answer by orouit Saturday, December 01, 2012 11:02 AM
    Thursday, November 29, 2012 5:33 PM
  • A new and better workaround has been provided:

    You can implement the interface like this in the Windows Runtime Component:

            string IPerson.Surname
            {
                get
                {
                    return surname;
                }
                set
                {
                    surname = value;
                }
            }

    Hope this helps.

    Cheers.


    Helge Mahrt - Microsoft Developer Support Engineer - If my reply answers your question, please mark this post as answered.

    Tuesday, December 11, 2012 4:32 PM