2013-05-28 14 views
9

Nie spałem od jakiegoś czasu, więc prawdopodobnie jest to łatwiejsze niż myślę.Rzuć obiekt typowym typem

mam rodzajowe klasy, który jest mniej więcej tak:

public class Reference<T> where T : APIResource //<- APIResource is abstract btw 
{ 
    private T _value = null; 
    public T value 
    { 
     get { return _value; } 
    } 
} 

Gdzie indziej, w sposób niestandardowy serializacji, ktoś przechodzi w object który jest faktycznie instancja Reference<(something)>. Ja po prostu chcę, aby przejść do „wartości” własności, że każdy Reference<> obiekt ma, więc chcę, aby przejść:

string serialize(object o) 
{ 
    return base.serialize(((Reference<>) o).value); 
} 

Oczywiście, życie nie jest takie proste, bo jak kompilator umieszcza go:

using the generic type "Reference<T>" requires 1 type arguments

Jak mogę zrobić to, co chcę zrobić?

Odpowiedz

14

Można utworzyć kowariantna rodzajowy interfejs właściwości:

interface IReference<out T> where T : ApiResource { 
    T Value { get; } 
} 

Następnie można rzucić IReference<Anything> do IReference<object> lub IReference<ApiResource>.

+0

Nie wiedziałem absolutnie nic o kowariantnych interfejsach generycznych, więc bardzo się cieszę, że zwróciłem się do SO. Musiałem odpowiednio zmodyfikować klasę ogólną: 'public class Reference : IReference gdzie T: APIResource {...}'. To pozwala mi odzyskać właściwość Value za pomocą '((IReference ) o) .Value' – Alain

3

Odpowiedź SLaks jest idealna. Po prostu chcę go nieco rozszerzyć:

Czasami są sytuacje, w których nie można zastąpić klasy interfejsem. Tylko w przypadkach, że może chcesz używać dynamic funkcji, tak aby można było nazwać value właściwość:

string serialize(object o) 
{ 
    if(typeof(Reference<>) == o.GetType().GetGenericTypeDefinition()) 
     return base.serialize(((dynamic)o).value); 

    //in your case you will throw InvalidCastException 
    throw new ArgumentException("not a Reference<>", "o"); 
} 

Jest to kolejny opcje i radzę go używać bardzo ostrożnie.

+0

Dziękuję za rozwiązanie alternatywne. Najwyraźniej jest to ostatnia deska ratunku, ale bardzo ważne, aby mieć tu na wypadek, gdyby ktoś nie mógł zmodyfikować danej klasy generycznej. – Alain

1

Nie zapomnij sprawdzić, czy jego typ rodzajowy lub nie ---> o.GetType(). IsGenericType przed

wykorzystaniem o.GetType()(). GetGenericTypeDefinition inny zgłasza wyjątek ..

Powiązane problemy