511

Is it possible to have an anonymous type implement an interface?

I've got a piece of code that I would like to work, but don't know how to do this.

I've had a couple of answers that either say no, or create a class that implements the interface construct new instances of that. This isn't really ideal, but I'm wondering if there is a mechanism to create a thin dynamic class on top of an interface which would make this simple.

public interface DummyInterface
{
    string A { get; }
    string B { get; }
}

public class DummySource
{
    public string A { get; set; }
    public string C { get; set; }
    public string D { get; set; }
}

public class Test
{
    public void WillThisWork()
    {
        var source = new DummySource[0];
        var values = from value in source
                     select new
                     {
                         A = value.A,
                         B = value.C + "_" + value.D
                     };

        DoSomethingWithDummyInterface(values);

    }

    public void DoSomethingWithDummyInterface(IEnumerable<DummyInterface> values)
    {
        foreach (var value in values)
        {
            Console.WriteLine("A = '{0}', B = '{1}'", value.A, value.B);
        }
    }
}

I've found an article Dynamic interface wrapping that describes one approach. Is this the best way of doing this?

Alexander Abakumov
  • 13,617
  • 16
  • 88
  • 129
Nick Randell
  • 17,805
  • 18
  • 59
  • 74
  • 1
    Link appears out of date, this maybe a suitable alternative http://www.liensberger.it/web/blog/?p=298. – Phil Cooper Jan 10 '13 at 10:13
  • 2
    Yes, you can do this with .NET 4 and higher (via the DLR), using the [ImpromptuInterface](https://www.nuget.org/packages/ImpromptuInterface/) nuget package. – BrainSlugs83 Dec 08 '16 at 23:50
  • 1
    @PhilCooper Your link has been down, probably since at least 2016 - but luckily it was archived before then. https://web.archive.org/web/20111105150920/http://www.liensberger.it/web/blog/?p=298 – Paul Mar 19 '20 at 09:39
  • in C#9 you can use records (https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/) I know this is not the same but also a very lightweight approach to implement "simple" interfaces :) – Marco Nov 10 '20 at 14:30

9 Answers9

390

No, anonymous types cannot implement an interface. From the C# programming guide:

Anonymous types are class types that consist of one or more public read-only properties. No other kinds of class members such as methods or events are allowed. An anonymous type cannot be cast to any interface or type except for object.

Kobi
  • 135,331
  • 41
  • 252
  • 292
HasaniH
  • 8,232
  • 6
  • 41
  • 59
  • 7
    would be nice to have this stuff anyway. If you're talking code readability, lambda expressions are usually not the way to go. If we're talking RAD, I'm all into java-like anonymous interface implementation. By the way, in some cases that feature is more powerful than delegates – Arsen Zahray Feb 16 '12 at 15:44
  • 21
    @ArsenZahray: lambda expressions, when used well, actually increase code readability. They're particularly powerful when used in functional chains, which can reduce or eliminate the need for local variables. – Roy Tinker Feb 29 '12 at 22:55
  • 4
    You could do the trick this way "Anonymous Implementation Classes – A Design Pattern for C#" - http://twistedoakstudios.com/blog/Post774_anonymous-implementation-classes-a-design-pattern-for-c – Dmitry Pavlov Nov 10 '14 at 15:48
  • 6
    @DmitryPavlov, that was surprisingly valuable. Passersby: [here](https://gist.github.com/kdbanman/34baea357f6e8203f285) is the condensed version. – kdbanman Sep 03 '15 at 18:02
  • 1
    you can cast the anonymous type to an anonymous object with the same fields http://stackoverflow.com/questions/1409734/cast-to-anonymous-type – Zinov May 26 '16 at 17:33
  • 1
    This answer is not entirely correct. -- This can be done in .NET 4.0 and higher using the DLR, it just takes a bit of glue and magic to make it all work. -- Luckily, there's a package called [ImpromptuInterface](https://www.nuget.org/packages/ImpromptuInterface/) that makes it really easy to do, and it lets you retroactively cast any object (even anonymous typed objects) to any interface (of course there will be late binding exceptions if you try to use a part of the interface that the class doesn't actually support). – BrainSlugs83 Dec 08 '16 at 23:56
  • Anonymous types are enormously useful in JSON serialisation when C# is used as a backbone for ajax calls and dynamic objects need to be created on the fly. (90% of the server code in some applications). – Karlth May 01 '17 at 20:51
97

While the answers in the thread are all true enough, I cannot resist the urge to tell you that it in fact is possible to have an anonymous class implement an interface, even though it takes a bit of creative cheating to get there.

Back in 2008 I was writing a custom LINQ provider for my then employer, and at one point I needed to be able to tell "my" anonymous classes from other anonymous ones, which meant having them implement an interface that I could use to type check them. The way we solved it was by using aspects (we used PostSharp), to add the interface implementation directly in the IL. So, in fact, letting anonymous classes implement interfaces is doable, you just need to bend the rules slightly to get there.

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Mia Clarke
  • 8,134
  • 3
  • 49
  • 62
  • 5
    It's a lot easier now; no need to modify the IL after the code is generated; just use [ImpromptuInterface](https://www.nuget.org/packages/ImpromptuInterface/). -- It lets you bind any object (including anonymously typed objects) to any interface (of course there will be late binding exceptions if you try to use a part of the interface that the class doesn't actually support). – BrainSlugs83 Dec 08 '16 at 23:57
48

Casting anonymous types to interfaces has been something I've wanted for a while but unfortunately the current implementation forces you to have an implementation of that interface.

The best solution around it is having some type of dynamic proxy that creates the implementation for you. Using the excellent LinFu project you can replace

select new
{
  A = value.A,
  B = value.C + "_" + value.D
};

with

 select new DynamicObject(new
 {
   A = value.A,
   B = value.C + "_" + value.D
 }).CreateDuck<DummyInterface>();
Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
Arne Claassen
  • 14,088
  • 5
  • 67
  • 106
  • 19
    [Impromptu-Interface Project](http://code.google.com/p/impromptu-interface/) will do this in .NET 4.0 using the DLR and is lighter weight then Linfu. – jbtule Mar 02 '11 at 04:51
  • Is `DynamicObject` a LinFu type? `System.Dynamic.DynamicObject` only has a protected constructor (at least in .NET 4.5). – jdmcnair Sep 11 '14 at 20:11
  • Yes. I was referring to the LinFu implementation of `DynamicObject` which predates the DLR version – Arne Claassen Sep 12 '14 at 04:58
16

Anonymous types can implement interfaces via a dynamic proxy.

I wrote an extension method on GitHub and a blog post http://wblo.gs/feE to support this scenario.

The method can be used like this:

class Program
{
    static void Main(string[] args)
    {
        var developer = new { Name = "Jason Bowers" };

        PrintDeveloperName(developer.DuckCast<IDeveloper>());

        Console.ReadKey();
    }

    private static void PrintDeveloperName(IDeveloper developer)
    {
        Console.WriteLine(developer.Name);
    }
}

public interface IDeveloper
{
    string Name { get; }
}
Jason Bowers
  • 496
  • 6
  • 12
13

No; an anonymous type can't be made to do anything except have a few properties. You will need to create your own type. I didn't read the linked article in depth, but it looks like it uses Reflection.Emit to create new types on the fly; but if you limit discussion to things within C# itself you can't do what you want.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • And important to note: properties may include functions or voids (Action) as well: select new { ... MyFunction = new Func(s => value.A == s) } works though you cannot refer to new properties in your functions (we can't use "A" in lieu of "value.A"). – cfeduke Oct 10 '08 at 12:39
  • 2
    Well, isn't that just a property that happens to be a delegate? It isn't actually a method. – Marc Gravell Oct 10 '08 at 13:15
  • 1
    I've used Reflection.Emit to create types at runtime but believe now I would prefer an AOP solution to avoid the runtime costs. – Norman H Sep 20 '13 at 12:55
10

The best solution is just not to use anonymous classes.

public class Test
{
    class DummyInterfaceImplementor : IDummyInterface
    {
        public string A { get; set; }
        public string B { get; set; }
    }

    public void WillThisWork()
    {
        var source = new DummySource[0];
        var values = from value in source
                     select new DummyInterfaceImplementor()
                     {
                         A = value.A,
                         B = value.C + "_" + value.D
                     };

        DoSomethingWithDummyInterface(values.Cast<IDummyInterface>());

    }

    public void DoSomethingWithDummyInterface(IEnumerable<IDummyInterface> values)
    {
        foreach (var value in values)
        {
            Console.WriteLine("A = '{0}', B = '{1}'", value.A, value.B);
        }
    }
}

Note that you need to cast the result of the query to the type of the interface. There might be a better way to do it, but I couldn't find it.

Doron Yaacoby
  • 9,412
  • 8
  • 48
  • 59
ICR
  • 13,896
  • 4
  • 50
  • 78
  • 2
    You could use `values.OfType()` instead of cast. It only returns the objects in your collection that actually can be cast to that type. It all depends on what you want. – Kristoffer L Jul 05 '10 at 13:57
9

The answer to the question specifically asked is no. But have you been looking at mocking frameworks? I use MOQ but there's millions of them out there and they allow you to implement/stub (partially or fully) interfaces in-line. Eg.

public void ThisWillWork()
{
    var source = new DummySource[0];
    var mock = new Mock<DummyInterface>();

    mock.SetupProperty(m => m.A, source.Select(s => s.A));
    mock.SetupProperty(m => m.B, source.Select(s => s.C + "_" + s.D));

    DoSomethingWithDummyInterface(mock.Object);
}
GregC
  • 7,737
  • 2
  • 53
  • 67
Russell Horwood
  • 1,015
  • 1
  • 11
  • 19
2

Another option is to create a single, concrete implementing class that takes lambdas in the constructor.

public interface DummyInterface
{
    string A { get; }
    string B { get; }
}

// "Generic" implementing class
public class Dummy : DummyInterface
{
    private readonly Func<string> _getA;
    private readonly Func<string> _getB;

    public Dummy(Func<string> getA, Func<string> getB)
    {
        _getA = getA;
        _getB = getB;
    }

    public string A => _getA();

    public string B => _getB();
}

public class DummySource
{
    public string A { get; set; }
    public string C { get; set; }
    public string D { get; set; }
}

public class Test
{
    public void WillThisWork()
    {
        var source = new DummySource[0];
        var values = from value in source
                     select new Dummy // Syntax changes slightly
                     (
                         getA: () => value.A,
                         getB: () => value.C + "_" + value.D
                     );

        DoSomethingWithDummyInterface(values);

    }

    public void DoSomethingWithDummyInterface(IEnumerable<DummyInterface> values)
    {
        foreach (var value in values)
        {
            Console.WriteLine("A = '{0}', B = '{1}'", value.A, value.B);
        }
    }
}

If all you are ever going to do is convert DummySource to DummyInterface, then it would be simpler to just have one class that takes a DummySource in the constructor and implements the interface.

But, if you need to convert many types to DummyInterface, this is much less boiler plate.

Gordon Bean
  • 4,272
  • 1
  • 32
  • 47
0

Using Roslyn, you can dynamically create a class which inherits from an interface (or abstract class).

I use the following to create concrete classes from abstract classes.

In this example, AAnimal is an abstract class.

var personClass = typeof(AAnimal).CreateSubclass("Person");

Then you can instantiate some objects:

var person1 = Activator.CreateInstance(personClass);
var person2 = Activator.CreateInstance(personClass);

Without a doubt this won't work for every case, but it should be enough to get you started:

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace Publisher
{
    public static class Extensions
    {
        public static Type CreateSubclass(this Type baseType, string newClassName, string newNamespace = "Magic")
        {
            //todo: handle ref, out etc.
            var concreteMethods = baseType
                                    .GetMethods()
                                    .Where(method => method.IsAbstract)
                                    .Select(method =>
                                    {
                                        var parameters = method
                                                            .GetParameters()
                                                            .Select(param => $"{param.ParameterType.FullName} {param.Name}")
                                                            .ToString(", ");

                                        var returnTypeStr = method.ReturnParameter.ParameterType.Name;
                                        if (returnTypeStr.Equals("Void")) returnTypeStr = "void";

                                        var methodString = @$"
                                        public override {returnTypeStr} {method.Name}({parameters})
                                        {{
                                            Console.WriteLine(""{newNamespace}.{newClassName}.{method.Name}() was called"");
                                        }}";

                                        return methodString.Trim();
                                    })
                                    .ToList();

            var concreteMethodsString = concreteMethods
                                        .ToString(Environment.NewLine + Environment.NewLine);

            var classCode = @$"
            using System;

            namespace {newNamespace}
            {{
                public class {newClassName}: {baseType.FullName}
                {{
                    public {newClassName}()
                    {{
                    }}

                    {concreteMethodsString}
                }}
            }}
            ".Trim();

            classCode = FormatUsingRoslyn(classCode);


            /*
            var assemblies = new[]
            {
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile(baseType.Assembly.Location),
            };
            */

            var assemblies = AppDomain
                        .CurrentDomain
                        .GetAssemblies()
                        .Where(a => !string.IsNullOrEmpty(a.Location))
                        .Select(a => MetadataReference.CreateFromFile(a.Location))
                        .ToArray();

            var syntaxTree = CSharpSyntaxTree.ParseText(classCode);

            var compilation = CSharpCompilation
                                .Create(newNamespace)
                                .AddSyntaxTrees(syntaxTree)
                                .AddReferences(assemblies)
                                .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            using (var ms = new MemoryStream())
            {
                var result = compilation.Emit(ms);
                //compilation.Emit($"C:\\Temp\\{newNamespace}.dll");

                if (result.Success)
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    Assembly assembly = Assembly.Load(ms.ToArray());

                    var newTypeFullName = $"{newNamespace}.{newClassName}";

                    var type = assembly.GetType(newTypeFullName);
                    return type;
                }
                else
                {
                    IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
                        diagnostic.IsWarningAsError ||
                        diagnostic.Severity == DiagnosticSeverity.Error);

                    foreach (Diagnostic diagnostic in failures)
                    {
                        Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
                    }

                    return null;
                }
            }
        }

        public static string ToString(this IEnumerable<string> list, string separator)
        {
            string result = string.Join(separator, list);
            return result;
        }

        public static string FormatUsingRoslyn(string csCode)
        {
            var tree = CSharpSyntaxTree.ParseText(csCode);
            var root = tree.GetRoot().NormalizeWhitespace();
            var result = root.ToFullString();
            return result;
        }
    }
}
Fidel
  • 7,027
  • 11
  • 57
  • 81