在C#中动态实现接口的最佳方式是什么?

在C#中动态实现接口的最佳方式是什么?,c#,dynamic,interface,C#,Dynamic,Interface,我经常发现,仅仅因为某个方法调用需要一次接口,就必须实现一个接口,这会让我分心。我必须在其他地方创建一个类,实现接口等等 Java有一个名为的特性,它允许实现接口“内联”。因此,我的问题是:使用现有的语法(我意识到“最好的”是主观的),你能想到用C#完成类似的事情的最好方式是什么。我在寻找好的语法,不一定是性能 我在C#中实现了以下POC: 给定 接口IFoobar { 布尔Foobar(字符串s); } IFoobar foo=Implement.Interface(新{ Foobar=new

我经常发现,仅仅因为某个方法调用需要一次接口,就必须实现一个接口,这会让我分心。我必须在其他地方创建一个类,实现接口等等

Java有一个名为的特性,它允许实现接口“内联”。因此,我的问题是:使用现有的语法(我意识到“最好的”是主观的),你能想到用C#完成类似的事情的最好方式是什么。我在寻找好的语法,不一定是性能

我在C#中实现了以下POC:

给定

接口IFoobar
{
布尔Foobar(字符串s);
}
IFoobar foo=Implement.Interface(新{
Foobar=newfunc(s=>s==“Foobar”)
});
这使用匿名对象和一些反射/发射来实现
IFoobar
接口(忽略属性、通用方法和重载)。但是,我不喜欢
新的Func
功能,但我不能没有它

环顾四周,我注意到一个名为的库,但它支持方法的语法并没有给我留下深刻印象

有“更好”的方法吗

编辑:我不是在寻找Java vs C#flame wars。

公共类Foo
public class Foo
{
   public Func<string,bool> TheDelegate {get;set;}
}

public class Bar
{
   public bool Implementation(string s)
   {
      return s == "True";
   }
}

public class Usage
{
    var myBar = new Bar();
    var myFoo = new Foo { TheDelegate = myBar.Implementation };

    //Or

    var myFoo = new Foo { TheDelegate = x => x == "True" };   
    //This removes the need for Bar completely
}
{ 公共函数delegate{get;set;} } 公共类酒吧 { 公共bool实现(字符串s) { 返回s==“True”; } } 公共类用法 { var myBar=新条(); var myFoo=newfoo{TheDelegate=myBar.Implementation}; //或 var myFoo=newfoo{TheDelegate=x=>x==“True”}; //这完全消除了对Bar的需要 }

正如您在上面的示例中所看到的,在C#中完全不需要类似java的攻击,C#是一种更好的语言。

您提到您不需要经常这样做,不关心性能,通常希望在单元测试期间这样做。为什么不使用模拟框架呢

例如,以库为例:

public interface IFoobar {
   Boolean Foobar(String s);
}  

void Main() {
    var foo = new Mock<IFoobar>();
    foo.Setup(x => x.Foobar(It.IsAny<string>()))
       .Returns((string s) => s == "foobar");

    foo.Object.Foobar("notbar"); // false
    foo.Object.Foobar("foobar"); // true
}
公共接口IFoobar{
布尔Foobar(字符串s);
}  
void Main(){
var foo=newmock();
Setup(x=>x.Foobar(It.IsAny())
.Returns((字符串s)=>s==“foobar”);
foo.Object.Foobar(“notbar”);//false
foo.Object.Foobar(“Foobar”);//true
}
看一下“即兴界面”()

它将允许你做一些像

class Program
{
    static void Main(string[] args)
    {
        Bar b = new Bar();
        b.DoSomethingWithFoo(new
        {
            Foobar = Return<string>.Arguments<string>(r => "foo")
        }.ActLike<IFoo>());
    }
}

public interface IFoo
{
    string Foobar(String s);
}

public class Bar
{
    public void DoSomethingWithFoo(IFoo foo)
    {
        Console.WriteLine(foo.Foobar("Hello World"));
    }
}
类程序
{
静态void Main(字符串[]参数)
{
杆b=新杆();
b、 DoSomethingWithFoo(新)
{
Foobar=Return.Arguments(r=>“foo”)
}.ActLike());
}
}
公共接口IFoo
{
字符串Foobar(字符串s);
}
公共类酒吧
{
公共无效DoSomethingWithFoo(IFoo-foo)
{
Console.WriteLine(foo.Foobar(“你好世界”);
}
}

可以使用更干净的lambda语法,但代价是
Create()
中的静态类型检查

我可以使用ImpromptuInterface来执行此操作:

IFoobar foo = Implement.Interface(new {
    Foobar = Function.Create(s => s == "foobar"),
});
通过创建以下类:

public static class Implement{

    public static dynamic Interface(object source){
        return Impromptu.ActLike(source);
    }

}

public static class Function{

    public static Func<dynamic> Create(Func<dynamic> del){
        return del;
    }

    public static Func<dynamic,dynamic> Create(Func<dynamic,dynamic> del){
        return del;
    }
    public static Func<dynamic,dynamic,dynamic> Create(Func<dynamic,dynamic, dynamic> del){
        return del;
    }

    public static Func<dynamic,dynamic,dynamic,dynamic> Create(Func<dynamic,dynamic, dynamic,dynamic> del){
        return del;
    }
    //...Add more if you want
}
公共静态类实现{
公共静态动态接口(对象源){
即兴返回ActLike(来源);
}
}
公共静态类函数{
公共静态函数创建(函数删除){
返回del;
}
公共静态函数创建(函数删除){
返回del;
}
公共静态函数创建(函数删除){
返回del;
}
公共静态函数创建(函数删除){
返回del;
}
//…如果需要,请添加更多
}

在C语言中实现所需功能的一个好方法是:

您可以装饰一个匿名类型,如下所示:

//Anonymous Class
var anon = new {Foobar= Return<bool>.Arguments<string>(s => s == "foobar")};

var myInterface = anon.ActLike<IFoobar>();

如果您想实现多个接口,请查看我的答案。

不幸的是,C#中的匿名类无法实现Java中的接口。但是,您可以创建某种适配器类,而不需要对外部项目有任何附加依赖关系。只需使用
Func
创建一个实现接口的基类:

interface IFoo
{
    bool DoSomething(string value);
}
class Bar : IFoo
{
    private readonly Func<string, bool> m_DoSomething;
    public Bar(Func<string, bool> DoSomething) { this.m_DoSomething = DoSomething; }

    public bool DoSomething(string value)
    { 
        return this.m_DoSomething(value);
    } 
}
或者也可以使用更明显的方法,特别是如果您的接口有不止一种方法:

var result = new Bar(DoSomething: x => true);

唯一的缺点是,对于您拥有的每个接口,都需要一个实现类。因此,只有当您希望以不同的行为多次实现每个接口时,这种方法才有用。因此,每当我需要为同一接口使用不同的实现时,我都会使用这种方法。

如果您最大的抱怨是在其他地方实现该接口,为什么不直接在您的方法之前/之后创建一个嵌套类呢?(与Java静态嵌套类相比。)


这比创建/使用一些动态framew(基本上是一个静态嵌套类)更为惯用的C语言。

我经常发现,仅仅因为某个方法调用需要一次接口就必须实现它,这会让我分心。
-使用
委托
。这就是C#与java的区别所在。你发现自己经常这样做吗?不,时不时地这样做,也许在编写单元测试时更是如此。我意识到这不一定是一个好的实践,但我很好奇,“我的问题不是关于Java的匿名类和C#delegate。”我的答案也不是。但是如果你不想听的话,我也没意见。嗯,ImpromptuInterface有你确切的POC语法,只需将
import.Interface
交换为
Impromptu.ActLike
,这样
IFoobar foo=Impromptu.ActLike(new{Foobar=new Func(s=>s==“Foobar”)此示例未实现原始问题中的
IFoobar
接口。如何将实现传递给一个采用
IFoobar
实例的方法?@user10789在C#中不需要这样的接口,因为存在委托。完全从代码中删除该接口,并在需要定义此类“可互换方法”时放置一个委托声明。@Marcus说,“实现一个接口只是因为我需要它一次用于某个方法调用”。。。“编写单元测试时更是如此”。我想是h
public Interface IFoobar
{
   bool Foobar(string s);
}
//Anonymous Class
var anon = new {Foobar= Return<bool>.Arguments<string>(s => s == "foobar")};

var myInterface = anon.ActLike<IFoobar>();
dynamic expando = Build<ExpandoObject>.NewObject(Foobar: Return<bool>.Arguments<string>(s => s == "foobar"));

IMyInterface myInterface = Impromptu.ActLike(expando);
interface IFoo
{
    bool DoSomething(string value);
}
class Bar : IFoo
{
    private readonly Func<string, bool> m_DoSomething;
    public Bar(Func<string, bool> DoSomething) { this.m_DoSomething = DoSomething; }

    public bool DoSomething(string value)
    { 
        return this.m_DoSomething(value);
    } 
}
var result = new Bar(x => true);
var result = new Bar(DoSomething: x => true);