Implizite / Explizite Konvertierung in Bezug auf das Schlüsselwort "as"

Ich versuche, einige Unit-Tests für ein Projekt durchzuführen, das leider ein hohes Maß an Interdependenz zwischen den Units aufweist. Gegenwärtig orientieren sich viele unserer Klassen an einem benutzerdefinierten UserIdentity Objekt, um die Authentifizierung zu bestimmen, aber dieses Objekt hat eine Menge internes Hoop-Jumping, das ich genauso schnell vermeiden würde, wenn ich versuchen würde, die Funktionalität einzelner Einheiten zu testen.

Um dies zu umgehen, versuche ich, eine "Schein" -Version dieser UserIdentity zu erstellen, die mit einer stärker kontrollierten Variablenumgebung verbunden werden kann.

urz gesagt, wir haben eine UserIdentity-Klasse mit mehreren öffentlichen schreibgeschützten Eigenschaften und einer statischen CurrentIdentity IIdentity) Platzhalter. Ich kann so ziemlich alles mit einem "Mock" umgehen IIdentity -Implementierung, aber ich stoße auf eine Wand, wenn ich einen Punkt erreiche, an dem die CurrentIdentity als @ umgewandelt wir UserIdentity.

Es ist eine ziemlich einfache Methode:

internal static UserIdentity GetCurrentIdentity()
{
    UserIdentity currentIdentity = ApplicationContext.User.Identity as UserIdentity;
    return currentIdentity;
}

Ich habe mein Mock-Objekt so eingerichtet, dass ein Mitglied der @ erstellt wir UserIdentity eingeben und dann so etwas machen:

    public static implicit operator UserIdentity(MockUserIdentity src)
    {
        return src.UserIdentity;
    }

oder diese

    public static explicit operator UserIdentity(MockUserIdentity src)
    {
        return src.UserIdentity;
    }

Das Problem ist, dass, soweit ich das beurteilen kann, "as" anscheinend keine implizite oder explizite Konvertierungsoperation für mein Scheinobjekt aufruft. Meine Frage (n) ist (sind?), Fehlt hier etwas Einfaches oder funktioniert dies nicht, da (ich vermute) die 'as'-Operation direkt auf die Klassenvererbung abzielt (was mein Objekt nicht tut ...) ?

Auch ein bisschen abseits des Themas, aber warum kann es nicht gleichzeitig explizite und implizite Operatoren desselben resultierenden Typs in einer Klasse geben? Wenn ich nichts Dummes verpasse, bremst der Compiler, wenn ich versuche, beide Konvertierungsoperatoren gleichzeitig zu haben. Ich muss den einen oder anderen auswählen.

AKTUALISIERE

Okay, jetzt bin ich gründlich verwirrt. Vielleicht werde ich schlampig, aber ich habe versucht, die Direktbesetzung zu machen, und ich scheine auch nicht dazu zu kommen, dass das funktioniert. Ich habe den Operator bei MSDN nachgelesen, und das Beispiel zeigt, dass der Operator in die resultierende Klasse und nicht in die Quellklasse übergeht, aber ich bin mir nicht sicher, ob das wichtig ist oder nicht (ich habe beide Stellen im folgenden Code ausprobiert). In jedem Fall habe ich versucht, einen einfachen Prüfstand einzurichten, um festzustellen, was ich möglicherweise falsch mache, aber auch das kann ich nicht zum Laufen bringe

class Program
{
    // Shared Interface
    public interface IIdentity { }

    // "real" class (not conducive to inheritence)
    public class CoreIdentity : IIdentity
    {
        internal CoreIdentity() { }

        // Just in case (if this has to be here, that seems unfortunate)
        public static explicit operator CoreIdentity(ExtendedIdentity src)
        {
            return src.Identity;
        }
    }

    // "mock" class (Wraps core object)
    public class ExtendedIdentity : IIdentity
    {
        public CoreIdentity Identity { get; set; }
        public ExtendedIdentity()
        {
            Identity = new CoreIdentity();
        }

        // This is where the operator seems like it should belong...
        public static explicit operator CoreIdentity(ExtendedIdentity src)
        {
            return src.Identity;
        }
    }

    // Dummy class to obtain "current core identity"
    public class Foo
    {
        public IIdentity Identity { get; set; }
        public CoreIdentity GetCoreIdentity()
        {
            return (CoreIdentity)Identity;
        }
    }

    static void Main(string[] args)
    {
        ExtendedIdentity identity = new ExtendedIdentity();
        Foo foo = new Foo();
        foo.Identity = identity;
        CoreIdentity core = foo.GetCoreIdentity();
    }
}

Aber das löst die folgende Ausnahme aus, wenn ich foo.GetCoreIdentity () aufrufe:

Objekt vom Typ 'ExtendedIdentity' kann nicht in 'CoreIdentity' umgewandelt werden.

und ich kann keinen meiner expliziten Operatoren mit einem Haltepunkt abfangen. Es sieht also so aus, als würde ich diese Entscheidung treffen, ohne die von mir bereitgestellten Konvertierungsrouten zu "probieren".

icherlich fehlt mir etwas Offensichtliches. Verhindert die Tatsache, dass ich meine Identität (in Foo) als IIdentity definiert habe, irgendwie die Auflösung der Besetzung unter Verwendung der expliziten Operatoren des implementierenden Typs? Das würde mich seltsam finden.

UPDATE (# 2)

Ich habe das Gefühl, dass ich meinen Post mit all diesen Updates spamme (vielleicht sollte ich meine Handlung zusammenbringen, bevor ich so triggerglücklich bin :)). Wie auch immer, ich habe die GetCoreIdentityMethod meines Foo dahingehend geändert:

public CoreIdentity GetCoreIdentity()
{
    ExtendedIdentity exId = Identity as ExtendedIdentity;
    if (exId != null)
        return (CoreIdentity)exId;

    return (CoreIdentity)Identity;
}

and (nachdem der mehrdeutige Verweis, der durch den Operator in beiden Klassen verursacht wurde, bereinigt werden musste), wurde mein expliziter Konvertierungsoperatorcode aufgerufen und es funktionierte wie erwartet. Es sieht also so aus, als wären die expliziten Operatoren nicht polymorph aufgelöst (ist das das richtige Verständnis?), Und die Tatsache, dass meine Eigenschaft eher als IIdentity als als ExtendedIdentity typisiert wurde, verhinderte, dass sie die Umwandlungslogik aufrief, obwohl sie von der war ExtendedIdentity-Typ zum Zeitpunkt des Aufrufs. Das kommt mir sehr merkwürdig und unerwartet vor .... und irgendwie bedauerlich.

Ich möchte nicht den Keeper des CurrentIdentity-Objekts neu schreiben müssen, um ihn auf meine speziellen Testmodelle aufmerksam zu machen. Ich wollte diese "spezielle" Logik in das Mock selbst einbinden, also ist das wirklich eine Schleife für mich.

Antworten auf die Frage(8)

Ihre Antwort auf die Frage