匿名型にインターフェースを実装させることは可能ですか。作業したいコードがありますが、その方法がわかりません。
私は、ノーと言うか、インターフェースを実装するクラスを作成して、その新しいインスタンスを作成するという、いくつかの答えを得ました。これは実際には理想的ではありませんが、これを単純にするインターフェースの上に薄い動的クラスを作成するためのメカニズムがあるかどうか疑問に思います。
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);
}
}
}
記事を見つけました動的インターフェースの折り返しそれは1つのアプローチを説明します。これはこれを行うための最善の方法ですか?
いいえ、匿名型はインターフェースを実装できません。からC#プログラミングガイド:
匿名型は、1つ以上の公開読み取り専用プロパティで構成されるクラス型です。メソッドやイベントなど、他の種類のクラスメンバーは許可されません。匿名型は、オブジェクト以外のインターフェイスまたは型にはキャストできません。
これは2年前の質問かもしれませんが、スレッド内の答えはすべて十分に真実ですが、実際にそれを伝えたいという衝動には耐えられません。可能です匿名クラスにインターフェースを実装させるには、そこに到達するために少し創造的な不正行為が必要です。
2008年に私は当時の雇用者のためにカスタムLINQプロバイダを書いていました、そしてある時点で私は他の匿名クラスから "私"の匿名クラスを伝えることができる必要がありました。それら。私たちがそれを解決した方法はアスペクトを使うことでしたポストシャープ)、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>();
DynamicObject
LinFuタイプ?System.Dynamic.DynamicObject
保護されたコンストラクタのみを持ちます(少なくとも.NET 4.5では)。 - jdmcnairDynamicObject
これはDLRバージョンより前のものです。 - Arne Claassen
いいえ。匿名型は、いくつかのプロパティを持つ以外は何もできません。あなたはあなた自身のタイプを作成する必要があるでしょう。リンクされた記事は詳しく読みませんでしたが、Reflection.Emitを使用して新しい型をその場で作成しているようです。議論を物事に限定した場合C#自体の中にあなたが望むことをすることはできません。
匿名型は動的プロキシを介してインタフェースを実装できます。
拡張メソッドを書いた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; }
}
最善の解決策は、無名クラスを使用しないことです。
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);
}
}
}
クエリの結果をインタフェースの型にキャストする必要があることに注意してください。もっと良い方法があるかもしれませんが、見つけることができませんでした。
values.OfType<IDummyInterface>()
キャストではなく実際にその型にキャストできるコレクション内のオブジェクトのみを返します。それはすべてあなたが望むものに依存します。 - Kristoffer L
具体的に尋ねられた質問に対する答えはノーです。しかし、あなたはモックフレームワークを見てきましたか?私は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);
}