Pergunta

É possível ter um tipo anônimo implementar uma interface. Eu tenho um pedaço de código que eu gostaria de trabalhar, mas não sei como fazer isso.

Eu tive um par de respostas que quer dizer não, ou criar uma classe que implementa a construção nova interface instâncias desse. Isto não é realmente ideal, mas eu estou querendo saber se há um mecanismo para criar uma classe dinâmica fina no topo de uma interface que faria este simples.

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

Eu encontrei um artigo Dinâmico que descreve uma abordagem. É esta a melhor maneira de fazer isso?

Foi útil?

Solução

Não, tipos anônimos não pode implementar uma interface. Do C # guia de programação :

tipos anônimos são tipos de classe que consistem em um ou propriedades somente leitura mais públicas. Não são permitidos outros tipos de membros da classe como métodos ou eventos. Um tipo anônimo não pode ser convertido para qualquer interface ou tipo de exceção de objeto.

Outras dicas

Embora isso possa ser uma questão de dois anos, e enquanto as respostas no fio são todas verdadeiras o suficiente, eu não posso resistir ao impulso de dizer-lhe que de fato é possível para ter um anônimo classe implementar uma interface, mesmo que leva um pouco de batota criativo para chegar lá.

Em 2008 eu estava escrevendo um provedor LINQ personalizado para o meu patrão, em seguida, e em um ponto que eu precisava para ser capaz de dizer "meus" classes anônimas de outros anônimos, o que significava que têm-los a implementar uma interface que eu poderia usar para digitar vê-los. A forma como resolvemos que era usando aspectos (usamos PostSharp ), para adicionar a implementação da interface directamente no IL. Então, na verdade, deixando classes anônimas implementar interfaces é factível , você só precisa dobrar as regras um pouco para chegar lá.

Fundição tipos anônimos a interfaces tem sido algo que eu queria há um tempo, mas, infelizmente, as forças de implementação atuais você ter uma implementação dessa interface.

A melhor solução em torno dele está tendo algum tipo de proxy dinâmico que cria a implementação para você. Usando o excelente LinFu projeto você pode substituir

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

com

 select new DynamicObject(new
 {
   A = value.A,
   B = value.C + "_" + value.D
 }).CreateDuck<DummyInterface>();

tipos anônimos podem implementar interfaces através de um proxy dinâmico.

Eu escrevi um método de extensão em GitHub e um post http://wblo.gs/feE para suportar este cenário.

O método pode ser usado como este:

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

Não; um tipo anônimo não pode ser feito para fazer qualquer coisa, exceto tem algumas propriedades. Você vai precisar para criar seu próprio tipo. Eu não li o artigo ligado em profundidade, mas parece que ele usa Reflection.Emit para criar novos tipos em tempo real; mas se você limitar a discussão de coisas dentro C # si você não pode fazer o que quiser.

A melhor solução é apenas para não usar classes anônimas.

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 que você precisa para converter o resultado da consulta para o tipo de interface. Pode haver uma maneira melhor de fazer isso, mas eu não poderia encontrá-lo.

A resposta para a pergunta especificamente solicitado não é. Mas você esteve olhando para zombar estruturas? Eu uso MOQ mas há milhões deles lá fora, e eles permitem que você implementar / ramal (parcial ou totalmente) interfaces de in-line. Por exemplo.

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

Outra opção é criar uma classe única, concreta implementação que leva lambdas no construtor.

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

Se tudo que você nunca vai fazer é convertido DummySource para DummyInterface, então seria mais simples ter apenas uma classe que leva um DummySource no construtor e implementa a interface.

Mas, se você precisa converter muitos tipos de DummyInterface, este é muito menos placa de caldeira.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top