Czy możliwe jest, aby anonimowy typ zaimplementował interfejs?
Mam kawałek kodu, który chciałbym pracować, ale nie wiem, jak to zrobić.
Mam kilka odpowiedzi, które albo mówią „nie”, albo tworzę klasę, która implementuje interfejs, konstruuje nowe instancje tego. To nie jest naprawdę idealne, ale zastanawiam się, czy istnieje mechanizm do tworzenia cienkiej dynamicznej klasy na interfejsie, który by tak uprościł.
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);
}
}
}
Znalazłem artykuł Zawijanie interfejsu dynamicznego, który opisuje jedno podejście. Czy to najlepszy sposób na zrobienie tego?
c#
anonymous-types
Nick Randell
źródło
źródło
Odpowiedzi:
Nie, typy anonimowe nie mogą implementować interfejsu. Z przewodnika po programowaniu w C # :
źródło
Chociaż może to być pytanie dwuletnie i chociaż wszystkie odpowiedzi w wątku są wystarczająco prawdziwe, nie mogę się oprzeć pokusie, aby powiedzieć, że w rzeczywistości możliwe jest, aby anonimowa klasa zaimplementowała interfejs, nawet jeśli wymaga to trochę kreatywnego oszukiwania, aby się tam dostać.
W 2008 roku pisałem niestandardowego dostawcę LINQ dla mojego ówczesnego pracodawcy, i w pewnym momencie musiałem móc odróżnić „moje” anonimowe klasy od innych anonimowych, co oznaczało, że musieliby oni zaimplementować interfejs, którego mógłbym użyć do sprawdzania typu im. Sposób, w jaki to rozwiązaliśmy, polegał na użyciu aspektów (użyliśmy PostSharp ), aby dodać implementację interfejsu bezpośrednio w IL. W rzeczywistości pozwolenie anonimowym klasom na implementację interfejsów jest wykonalne , wystarczy lekko zgiąć reguły, aby się tam dostać.
źródło
Rzucanie anonimowych typów na interfejsy było czymś, czego chciałem od dłuższego czasu, ale niestety obecna implementacja zmusza cię do implementacji tego interfejsu.
Najlepszym rozwiązaniem jest posiadanie pewnego rodzaju dynamicznego serwera proxy, który tworzy dla Ciebie implementację. Korzystając z doskonałego projektu LinFu, możesz go wymienić
z
źródło
DynamicObject
to typ LinFu?System.Dynamic.DynamicObject
ma tylko chroniony konstruktor (przynajmniej w .NET 4.5).DynamicObject
której wersja poprzedza wersję DLRAnonimowe typy mogą implementować interfejsy za pośrednictwem dynamicznego serwera proxy.
Napisałem metodę rozszerzenia na GitHub i post na blogu http://wblo.gs/feE, aby wesprzeć ten scenariusz.
Metodę można zastosować w następujący sposób:
źródło
Nie; typu anonimowego nie można zmusić do robienia czegokolwiek poza kilkoma właściwościami. Musisz stworzyć własny typ. Nie przeczytałem dogłębnie tego artykułu, ale wygląda na to, że używa Reflection.Emit do tworzenia nowych typów w locie; ale jeśli ograniczysz dyskusję do rzeczy w samym C #, nie możesz robić tego, co chcesz.
źródło
Najlepszym rozwiązaniem jest po prostu nie używanie anonimowych klas.
Pamiętaj, że musisz rzutować wynik zapytania na typ interfejsu. Może być lepszy sposób, aby to zrobić, ale nie mogłem go znaleźć.
źródło
values.OfType<IDummyInterface>()
zamiast obsady. Zwraca tylko obiekty w Twojej kolekcji, które faktycznie można rzutować na ten typ. Wszystko zależy od tego, czego chcesz.Odpowiedź na zadane pytanie brzmi „nie”. Ale czy patrzyłeś na szydzące frameworki? Używam MOQ, ale są tam miliony i pozwalają one na implementację / stub (częściowo lub całkowicie) interfejsów w linii. Na przykład.
źródło
Inną opcją jest utworzenie pojedynczej, konkretnej klasy implementacyjnej, która przyjmuje lambdas w konstruktorze.
Jeśli wszystko, co kiedykolwiek zamiar zrobić, to konwersja
DummySource
doDummyInterface
, wtedy byłoby prościej po prostu jedną klasę, która trwaDummySource
w konstruktorze i implementuje interfejs.Ale jeśli musisz przekonwertować wiele typów
DummyInterface
, jest to znacznie mniej płyty kotła.źródło