0

As an example (and the reason of my question), the class Windows.XAML.Media.Transform, as far as I can see from the WinMD info shown by ILDASM, has no defined constructor.

But if I try to derive from that class, on my C# project, compiler complains that non constructor can be found.

This seems to me that this could be a result of hidden visibility of the constructor.

A same effect can be achieved in C# declaring a private (or internal) Constructor, but it must be declared, otherwise a public constructor is created by the compiler, and the class is indeed derivable.

Any hint?

  • take a look at this and tell me if it helps: http://stackoverflow.com/questions/3763612/default-visibility-for-c-sharp-classes-and-members-fields-methods-etc – turibbio Aug 29 '12 at 16:02

2 Answers2

3

I think what's going on here is, that the class has explicitly declared an internal (default) constructor, no public constructor(s), so the developers can inherit from the class within the defining assembly. Everybody else, outside the assembly is prevented from beeing able to inherit from the class.

Mithrandir
  • 24,869
  • 6
  • 50
  • 66
  • Ok, then my question is: why this info is not propagated to the meta info? Do the WinMD file show only the reachable details of the class? Thanks – Nicolò Carandini Aug 29 '12 at 16:07
  • 1
    @NicolòCarandini: the .winmd files show the published surface of a WinRT component, so yes in this case only the public members are visible. http://msdn.microsoft.com/en-us/library/windows/apps/hh755822.aspx – Mithrandir Aug 29 '12 at 16:19
  • Public and protected ("family") members, since protected members of composable classes are also part of the "public" API. – James McNellis Aug 29 '12 at 16:41
  • Thanks to all for the reply and the link – Nicolò Carandini Aug 29 '12 at 16:47
0

WinRT is an evolution of the COM concepts and is a quite different story as we are talking about binary components and not source inheritance. The most important thing in this ABI story is that the only things of the component that can be used are the ones exposed via interfaces. Constructors cannot be defined in interfaces nor can statics, and this means that WinRT need interfaces for these too.

C# viewes of WinRT components are an artifact of the language projection and not the real layout of the component. To fully understand what's there, you should look at the component in C++, using the native library WRL that is the library used to build the WinRT APIs.

The Constructor is a projection for the factory interface of the WinRT component (and statics, new to WinRT as they didn't exist in COM, have a similar treatment).

When you "new" from C# an object, a Factory component associated to the component is first created. After this the factory create the object. For this reason the constructor question should be seen in terms of factory component and not in terms of constructor (that exist in the underlying implementation but it doesn't really matter as what you see of the component is only its binary contract, the ABI).

So there are different options: 1. A factory does not exist and you cannot create the component. If the Factory interface is internal you can't use it and can't create the object. 2. A factory exists and expose the default constructor. In C# you can new the object 3. A custom factory exists and expose custom constructors (whit parameters).

ITransformFactory is private and I believe this explain the behavior you have seen.

There is much more on this topic as WinRT aggregation is the way they provide binary inheritance and versioning, but this is another (very long) story.

Still digging, and never will stop, that's the fun part of our job :)

raf
  • 131
  • 1
  • 4
  • Hi, Raf, I'm sorry but I don't think you're right saying: "ITransformFactory is private and I believe this explain the behavior you have seen". I think the Interface is private because is used internally to do all the things you have explained. All the interface are private! As an example, look at the class Windows.XAML.Media.RotateTransform, that I can instantiate. It has the Ctor, and the IRotateTransform is private too. So I think Mithrandir got the point and the answer is in the linked document. – Nicolò Carandini Aug 30 '12 at 17:17
  • Member accessibility and visibility: In a private ref class, interface, or delegate, no members are emitted to metadata, even if they have public accessibility. In public ref classes, you can control the visibility of members in metadata independently of their accessibility in your source code. As in standard C++, apply the principle of least privilege; don't make your members visible in metadata unless they absolutely must be. – Nicolò Carandini Aug 30 '12 at 17:19
  • I believe you missed the main point: factories are projected to the constructor. This means that the constructor that you see in C# is not the constructor but the projected factory over which you don't have control. Said that, it doesn't matter if this is caused by the visibility or the way the factory is built internally (as I wrote I am still digging this point). – raf Aug 30 '12 at 17:34
  • The linked document it's not about C#, is about C++/CX, and there are no projection involved in that case, as far as I know. Anyway, more to dig here, I do agree. – Nicolò Carandini Aug 30 '12 at 21:01