[C#] 익명 클래스가 인터페이스를 구현할 수 있습니까?

익명 유형으로 인터페이스를 구현할 수 있습니까?

작동하고 싶은 코드가 있지만이 작업을 수행하는 방법을 모르겠습니다.

아니오라고 말하거나 인터페이스를 구현하는 클래스를 작성하여 새로운 인스턴스를 생성하는 몇 가지 답변이 있습니다. 이것은 이상적이지는 않지만 인터페이스 위에 얇은 동적 클래스를 만들어서 간단하게 만들 수있는 메커니즘이 있는지 궁금합니다.

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

한 가지 접근 방식을 설명하는 동적 인터페이스 줄 바꿈 기사를 찾았습니다 . 이것이 최선의 방법입니까?



답변

아니요, 익명 유형은 인터페이스를 구현할 수 없습니다. 로부터 C # 프로그래밍 가이드 :

익명 형식은 하나 이상의 공용 읽기 전용 속성으로 구성된 클래스 형식입니다. 메서드 나 이벤트와 같은 다른 종류의 클래스 멤버는 허용되지 않습니다. 익명 유형은 객체를 제외한 모든 인터페이스 또는 유형으로 캐스트 할 수 없습니다.


답변

이것은 2 살짜리 질문 일지 모르지만 스레드의 대답은 모두 사실이지만 익명의 클래스가 인터페이스를 구현하는 것이 가능 하다는 사실을 말하려는 충동에 저항 할 수는 없습니다 . 거기에 도착하는 창의적인 속임수.

2008 년에 나는 당시 고용주를 위해 커스텀 LINQ 공급자를 작성하고 있었고, 언젠가는 다른 익명의 사람들로부터 “나의”익명 클래스를 말할 수 있어야했습니다. 그들. 우리가 해결 한 방법은 aspect ( PostSharp 사용 )를 사용 하여 인터페이스 구현을 IL에 직접 추가하는 것입니다. 사실, 익명 클래스가 인터페이스를 구현 하게하는 것은 가능합니다. 규칙을 약간 구부려 야합니다.


답변

익명 유형을 인터페이스에 캐스트하는 것은 한동안 원했던 것이었지만 불행히도 현재 구현에서는 해당 인터페이스를 구현해야합니다.

가장 좋은 해결책은 구현을 만드는 일종의 동적 프록시를 사용하는 것입니다. 우수한 LinFu 프로젝트 를 사용하면 교체 할 수 있습니다

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

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


답변

익명 유형은 동적 프록시를 통해 인터페이스를 구현할 수 있습니다.

이 시나리오를 지원하기 위해 GitHub에 확장 방법 과 블로그 게시물 http://wblo.gs/feE 를 작성했습니다 .

이 방법은 다음과 같이 사용할 수 있습니다.

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


답변

아니; 익명 유형은 몇 가지 속성을 제외하고는 아무것도 할 수 없습니다. 자신 만의 유형을 만들어야합니다. 링크 된 기사를 자세히 읽지는 않았지만 Reflection.Emit을 사용하여 새 유형을 즉석에서 만드는 것처럼 보입니다. 그러나 C # 자체의 내용으로 토론을 제한 하면 원하는 것을 수행 할 수 없습니다.


답변

가장 좋은 해결책은 익명 클래스를 사용하지 않는 것입니다.

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

조회 결과를 인터페이스 유형으로 캐스트해야합니다. 더 좋은 방법이 있지만 찾을 수 없었습니다.


답변

구체적으로 묻는 질문에 대한 대답은 ‘아니요’입니다. 그러나 모의 프레임 워크를보고 있습니까? 나는 MOQ를 사용하지만 수백만 개가 있으며 인라인으로 인터페이스를 (부분적으로 또는 완전히) 구현 / 스텁 할 수 있습니다. 예 :

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