【问题标题】:Create anonymous class that implements an interface创建实现接口的匿名类
【发布时间】:2013-09-06 10:36:28
【问题描述】:

我想知道是否有一些内联的短方法来创建实现接口的类。就像有匿名方法一样,但有实现接口。

问题是:

interface iSomeInterface
{
  void DoIt();
}

public void myMethod(iSomeInterface param)
{
 ...
}

我想这样使用它:

object.myMethod(new { override DoIt() { Console.WriteLine("yay"); } } : iSomeInterface);

有什么想法吗?

如有重复,请见谅。

【问题讨论】:

  • Func<T> 和 Action<T> 及其变体可能对您实现类似的目标有用...
  • 您可以使用 Moq - 这将严重滥用其目的,但它可以让您创建本质上是匿名的类。
  • 这并不意味着刻薄或粗鲁 - 真的......但我至少想建议你停止尝试在代码中找到'忍者一样棘手的把戏'来做事......尤其是那个 1 班轮 - 几乎让我尖叫......真的......作为一个提供应用程序支持的人(在新旧项目上工作,有时没有文档),我确信开发人员认为他们正在做的事情真的很酷,最终通常是一个 bug 潜入的地方。最重要的是,它很难维护,并且很难在一段时间后回来并知道你刚刚做了 WTF。
  • @ninjahedgehog 要在 c# 中解决这个问题,它不会是单行的。不要那么懒惰,创建一个新类。在您编写、维护和评论此堆栈的时间里,您可能已经编写了您需要的所有代码。

标签: c#


【解决方案1】:

抱歉,C# 中没有类的内联实现。只有Anonymous Types,但它们不支持添加接口(例如参见Can a C# anonymous class implement an interface?)(也不支持添加方法或字段...它们仅支持属性)。

你可以使用System.Reflection.Emit的方法在运行时生成一个类,但是它冗长乏味。

【讨论】:

  • @ninjahedgehog 有非忍者般的诡计。从技术上讲,您可以通过反射创建一个新类,但这将是非常多的工作。参见例如stackoverflow.com/questions/15733900/…
  • @ninjahedgehog 如果您想接受单方法接口(在您的情况下是一个 void 方法),请改为接受 Action。
  • 该死的,我正在寻找一个类似忍者的诡计。一个完成这项工作的静态方法,我只需要设置我希望作为参数注入的接口。
【解决方案2】:

您可以创建一个包装Action 并实现该接口的类:

public sealed class SomeAction : ISomeInterface
{
    Action action;
    public SomeAction (Action action) { this.action = action; }
    public void DoIt() { this.action(); }
}

这允许您按如下方式使用它:

object.myMethod(new SomeAction(() => Console.WriteLine("yay"));

这当然只有在你要重用SomeAction时才非常实用,但这可能是最方便的解决方案。

【讨论】:

    【解决方案3】:

    这在 java 中很常见,但在 C# 中无法做到。您可以将函数或过程作为参数传递:

    public void myMethod(Action act)
    {
        act();
    }
    
    myMethod( () => Console.WriteLine("yay") );
    

    存在多个(通用)版本的 Action(有参数但没有返回值的过程)和 Func(有参数和返回值的函数)。

    【讨论】:

      【解决方案4】:

      查找“ImpromptuInterface”NuGet 包。 通过这个包和 ExpandoObject 的结合,你可以做这样的事情

      //Create an expando object and create & assign values to all the fields that exists in your interface
      dynamic sigObj = new ExpandoObject();
      sigObj.EmployeeKey = 1234;
      
      //Create the object using "ActLike" method of the Impromptu class
      INewSignatureAcquired sig = Impromptu.ActLike<INewSignatureAcquired>(sigObj);
      

      【讨论】:

        猜你喜欢
        • 2016-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多