C# 匿名类可以实现接口吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/191013/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can anonymous class implement interface?
提问by Nick Randell
Is it possible to have an anonymous type implement an interface?
是否可以让匿名类型实现接口?
I've got a piece of code that I would like to work, but don't know how to do this.
我有一段我想工作的代码,但不知道如何做到这一点。
I've had a couple of answers that either say no, or create a class that implements the interface construct new instances of that. This isn't really ideal, but I'm wondering if there is a mechanism to create a thin dynamic class on top of an interface which would make this simple.
我有几个答案要么说不,要么创建一个实现接口的类来构造它的新实例。这并不是很理想,但我想知道是否有一种机制可以在接口之上创建一个瘦动态类,这会使这变得简单。
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);
}
}
}
I've found an article Dynamic interface wrappingthat describes one approach. Is this the best way of doing this?
我找到了一篇文章Dynamic interface wrapping描述了一种方法。这是最好的方法吗?
采纳答案by HasaniH
No, anonymous types cannot implement an interface. From the C# programming guide:
不,匿名类型不能实现接口。从C# 编程指南:
Anonymous types are class types that consist of one or more public read-only properties. No other kinds of class members such as methods or events are allowed. An anonymous type cannot be cast to any interface or type except for object.
匿名类型是由一个或多个公共只读属性组成的类类型。不允许使用其他类型的类成员,例如方法或事件。匿名类型不能转换为除 object 之外的任何接口或类型。
回答by Marc Gravell
No; an anonymous type can't be made to do anything except have a few properties. You will need to create your own type. I didn't read the linked article in depth, but it looks like it uses Reflection.Emit to create new types on the fly; but if you limit discussion to things within C# itselfyou can't do what you want.
不; 除了具有一些属性之外,匿名类型不能做任何事情。您将需要创建自己的类型。我没有深入阅读链接的文章,但看起来它使用 Reflection.Emit 来动态创建新类型;但是如果您将讨论限制在 C# 本身内部,您将无法做您想做的事。
回答by ICR
The best solution is just not to use anonymous classes.
最好的解决方案就是不使用匿名类。
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 that you need to cast the result of the query to the type of the interface. There might be a better way to do it, but I couldn't find it.
请注意,您需要将查询结果强制转换为接口类型。可能有更好的方法来做到这一点,但我找不到。
回答by Arne Claassen
Casting anonymous types to interfaces has been something I've wanted for a while but unfortunately the current implementation forces you to have an implementation of that interface.
将匿名类型转换为接口一直是我想要的一段时间,但不幸的是,当前的实现迫使您实现该接口。
The best solution around it is having some type of dynamic proxy that creates the implementation for you. Using the excellent LinFu projectyou can replace
最好的解决方案是使用某种类型的动态代理为您创建实现。使用优秀的LinFu项目可以替换
select new
{
A = value.A,
B = value.C + "_" + value.D
};
with
和
select new DynamicObject(new
{
A = value.A,
B = value.C + "_" + value.D
}).CreateDuck<DummyInterface>();
回答by Mia Clarke
While this might be a two year old question, and while the answers in the thread are all true enough, I cannot resist the urge to tell you that it in fact is possibleto have an anonymous class implement an interface, even though it takes a bit of creative cheating to get there.
虽然这可能是一个两年前的问题,虽然线程中的答案都足够真实,但我还是忍不住想告诉你,实际上可以让一个匿名类实现一个接口,即使它需要一个有点创造性的作弊才能到达那里。
Back in 2008 I was writing a custom LINQ provider for my then employer, and at one point I needed to be able to tell "my" anonymous classes from other anonymous ones, which meant having them implement an interface that I could use to type check them. The way we solved it was by using aspects (we used PostSharp), to add the interface implementation directly in the IL. So, in fact, letting anonymous classes implement interfaces is doable, you just need to bend the rules slightly to get there.
早在 2008 年,我正在为我当时的雇主编写一个自定义的 LINQ 提供程序,有一次我需要能够将“我的”匿名类与其他匿名类区分开来,这意味着让它们实现一个我可以用来进行类型检查的接口他们。我们解决它的方法是使用方面(我们使用PostSharp),直接在 IL 中添加接口实现。所以,事实上,让匿名类实现接口是可行的,你只需要稍微改变规则即可。
回答by Nine Tails
The answer to the question specifically asked is no. But have you been looking at mocking frameworks? I use MOQ but there's millions of them out there and they allow you to implement/stub (partially or fully) interfaces in-line. Eg.
具体问题的答案是否定的。但是您是否一直在研究模拟框架?我使用最小起订量,但那里有数百万个,它们允许您在线实现/存根(部分或全部)接口。例如。
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);
}
回答by Jason Bowers
Anonymous types can implement interfaces via a dynamic proxy.
匿名类型可以通过动态代理实现接口。
I wrote an extension method on GitHuband a blog post http://wblo.gs/feEto support this scenario.
我在GitHub 上写了一个扩展方法和一篇博客文章http://wblo.gs/feE来支持这个场景。
The method can be used like this:
该方法可以这样使用:
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; }
}
回答by Gordon Bean
Another option is to create a single, concrete implementing class that takes lambdas in the constructor.
另一种选择是创建一个单一的、具体的实现类,该类在构造函数中使用 lambda。
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);
}
}
}
If all you are ever going to do is convert DummySource
to DummyInterface
, then it would be simpler to just have one class that takes a DummySource
in the constructor and implements the interface.
如果您要做的只是转换DummySource
为DummyInterface
,那么只拥有一个DummySource
在构造函数中接受 a并实现接口的类会更简单。
But, if you need to convert many types to DummyInterface
, this is much less boiler plate.
但是,如果您需要将多种类型转换DummyInterface
为 .