首页 文章

C#匿名类可以实现接口吗?

提问于
浏览
397

是否可以使用匿名类型实现接口 . 我有一段我想要工作的代码,但不知道如何做到这一点 .

我有几个答案要么说不,要么创建一个实现接口的类构建新的实例 . 这不是很理想,但我想知道是否有一种机制可以在接口之上创建一个瘦动态类,这将使这个变得简单 .

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

我发现了一篇描述一种方法的文章Dynamic interface wrapping . 这是最好的方法吗?

7 回答

  • 12

    不,匿名类型无法实现接口 . 来自C# programming guide

    匿名类型是由一个或多个公共只读属性组成的类类型 . 不允许使用其他类别的成员,例如方法或事件 . 除对象外,无法将匿名类型强制转换为任何接口或类型 .

  • 12

    虽然这可能是一个两年前的问题,虽然线程中的答案都足够真实,但我无法抗拒告诉你实际上 is possible 有一个匿名类实现一个接口的冲动,即使它需要一点点到达那里的创造性作弊 .

    早在2008年,我就为我当时的雇主编写了一个自定义LINQ提供程序,有一次我需要能够从其他匿名类中告诉"my"匿名类,这意味着让它们实现一个我可以用来键入检查它们的接口 . 我们解决它的方法是使用方面(我们使用PostSharp),直接在IL中添加接口实现 . 所以,实际上, letting anonymous classes implement interfaces is doable ,你只需稍微弯曲规则即可到达那里 .

  • 11

    将匿名类型转换为接口已经是我想要的一段时间,但不幸的是,当前的实现迫使您拥有该接口的实现 .

    围绕它的最佳解决方案是使用某种类型的动态代理为您创建实现 . 使用优秀的LinFu project可以替换

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

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

    没有;一个匿名类型可以深入阅读链接文章,但看起来它使用Reflection.Emit动态创建新类型;但如果你把讨论局限于C#内部的事情,你就无法做你想做的事 .

  • 312

    最好的解决方案就是不要使用匿名类 .

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

    请注意,您需要将查询结果强制转换为接口类型 . 可能有更好的方法,但我找不到它 .

  • 82

    具体问到的问题的答案是否定的 . 但你有没有看过模拟框架?我使用MOQ,但那里有数以百万计的MOQ,它们允许你在线实现/ stub(部分或全部)接口 . 例如 .

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

    匿名类型可以通过动态代理实现接口 .

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

相关问题