Roslyn: Proposal: Meta-Contracts for Dynamics (For Tooling Improvements)

Created on 22 May 2015  路  11Comments  路  Source: dotnet/roslyn

Problem

Sometimes you are working with an object whose type you do not know, but know something about. For instance, I may be working with a dynamic object, but I may know that there will be a FirstName and LastName property. It would be nice to have a way to inform the tooling about the extra information that you know by declaring meta-contract information.

Problem domain

  • JSON Endpoints
  • Dynamic objects: Inter-language communication, Dynamic Database ORMs, etc
  • Passing anonymous objects
  • Multiple acceptable types without a shared sub-type

    Primary Objectives

  • Compile-time checks to enforce declared type information

  • Intellisense support for declared type information

    Solution Setup

Lets say we have a function that concatenates first a last name. The function does not care what type is passed as long as it has two properties: string FirstName and string LastName.

function string GetFullName(? entity)
{
    return entity.FirstName + " " + entity.LastName;
}

The consumer should feel free to pass any candidate type.

string fullName = GetFullName(new { FirstName = "John", LastName = "Doe" });

We could can achieve this today by making entity a type of dynamic, but we sacrifice tooling. We need a way to associate extra information with entity.

Solution

One solution would be to create an interface to serve as a contract and extend the syntax for dynamic to include the contract, dynamic<IMyContract>.

interface IEntityWithName
{
    string FirstName { get; }
    string LastName { get; }
}

function string GetFullName(dynamic<IEntityWithName> entity)
{
    return entity.FirstName + " " + entity.LastName;
}

Other Considerations

  • This problem is applicable to more than just dynamic entity types. An improvement on this solution would be to support adding the contract to any type. For instance, I may accept entities of type MyBaseType that also conform to the IEntityWithName contract.
  • The extra contract information could disappear during compilation since the goal is just to improve tooling. However, retaining the information would allow tooling improvements when consuming pre-compiled binaries as well.
  • Should multiple contracts (both A and B) be supported dynamic< IContractA & IContractB >?
  • Should alternative contracts (either A or B) be supported dynamic< IContractA | IContractB >?
Area-Language Design Discussion

Most helpful comment

@paulomorgado ImpromptuInterface is based on dynamic meaning you can totally meta-program the entire implementation behind the interface.

All 11 comments

Sounds like ducktyping, is overlapping with #2146 and #154

Similarities with #13, #154, #129

This is definitely something that we want to think about.

Jon Skeet talked about this back in 2008: http://blogs.msmvps.com/jonskeet/2008/10/30/c-4-0-dynamic-lt-t-gt/

You aren't really casting here or anything like that, it almost seems like a specific case of pattern matching. I think the syntaxes should align (#206).

I have been requesting that for years, with no luck.

The only difference is that I proposed dynamic(Type) in equivalence to default(Type) because there isn't any keyword in C# that uses <Type>.

There's no need to complicate type specifications. If you need it to implement more that one interface, define one that extends those.

I wonder how close could you get using just a library. For example, I could imagine something like:

c# string fullName = GetFullName(new { FirstName = "John", LastName = "Doe" }.AsDuckInterface<IEntityWithName>());

where the extension method AsDuckInterface<T>() would create a wrapper class that implements the interface T and forwards the implementation to the given object.

@svick there's one in case you're wondering ;) https://github.com/ekonbenefits/impromptu-interface

No! I want dynamic with everything that comes with it, plus static typing.

@paulomorgado ImpromptuInterface is based on dynamic meaning you can totally meta-program the entire implementation behind the interface.

We are now taking language feature discussion on https://github.com/dotnet/csharplang for C# specific issues, https://github.com/dotnet/vblang for VB-specific features, and https://github.com/dotnet/csharplang for features that affect both languages.

Was this page helpful?
0 / 5 - 0 ratings