528

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?

4

10 Answers 10

393

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.

Sign up to request clarification or add additional context in comments.

7 Comments

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
@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.
You could do the trick this way "Anonymous Implementation Classes – A Design Pattern for C#" - twistedoakstudios.com/blog/…
@DmitryPavlov, that was surprisingly valuable. Passersby: here is the condensed version.
you can cast the anonymous type to an anonymous object with the same fields stackoverflow.com/questions/1409734/cast-to-anonymous-type
|
101

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.

1 Comment

It's a lot easier now; no need to modify the IL after the code is generated; just use 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).
50

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>();

3 Comments

Impromptu-Interface Project will do this in .NET 4.0 using the DLR and is lighter weight then Linfu.
Is DynamicObject a LinFu type? System.Dynamic.DynamicObject only has a protected constructor (at least in .NET 4.5).
Yes. I was referring to the LinFu implementation of DynamicObject which predates the DLR version
17

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; }
}

Comments

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.

3 Comments

And important to note: properties may include functions or voids (Action) as well: select new { ... MyFunction = new Func<string,bool>(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").
Well, isn't that just a property that happens to be a delegate? It isn't actually a method.
I've used Reflection.Emit to create types at runtime but believe now I would prefer an AOP solution to avoid the runtime costs.
10

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);
}

1 Comment

I'm 10+ years late to the party, but beware: Moq objects keep track of all calls being made (so it can "verify" aftewards). Which means that if your Moq object is long lived, you may have a memory leak.
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.

2 Comments

You could use values.OfType<IDummyInterface>() 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.
Literally the worst solution to the question as asked lol
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.

Comments

1

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;
        }
    }
}

Comments

-3

Well, you could try JSonSerializer, DeSerializer to Serialize the anonymous object and then DeSerialize it to the interface.

                 var result = JsonSerializer.Deserialize<DummyInterface>(JsonSerializer.Serialize(AnonymousObject));

1 Comment

This won't work as-is. An intance of an interface cannot be constructed, only concrete types (classes, structs, records, etc) that implement the interface can be constructed. Thus deserialization to DummyInterface will fail unless you have a converter or some polymorphism attributes that specify the concrete type to be used.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.