Domanda

In generale, sto cercando di creare un PSCmdlet che accetta un parametro di un tipo che implementa IDisposeable e richiede l'eliminazione per evitare perdite di risorse.Vorrei anche accettare un string per quel parametro e creare un'istanza di quel tipo, tuttavia se creo quell'oggetto da solo, allora devo eliminarlo prima di tornare da ProcessRecord.

Sto usando un ArgumentTransformationAttribute con il mio parametro per costruire il mio oggetto IDisposeable da una stringa, ma non riesco a trovare alcun modo per passare i dati da quella classe al mio PSCmdlet se ho creato l'oggetto o meno.Ad esempio:

[Cmdlet("Get", "MyDisposeableName")]
public class GetMyDisposeableNameCommand : PSCmdlet
{
    [Parameter(Mandatory = true, Position = 0), MyDisposeableTransformation]
    public MyDisposeable MyDisposeable
    {
        get;
        set;
    }

    protected override void ProcessRecord()
    {
        try
        {
            WriteObject(MyDisposeable.Name);
        }
        finally
        {
            /* Should only dispose MyDisposeable if we created it... */
            MyDisposeable.Dispose();
        }
    }
}

class MyDisposeableTransformationAttribute : ArgumentTransformationAttribute
{
    public override Object Transform(EngineIntrinsics engineIntrinsics, Object input)
    {
        if (input is PSObject && ((PSObject)input).BaseObject is MyDisposeable)
        {
            /* We were passed a MyDisposeable, we should not dispose it */
            return ((PSObject)input).BaseObject;
        }

        /* We created a MyDisposeable, we *should* dispose it */
        return new MyDisposeable(input.ToString());
    }
}

La mia ipotesi migliore qui è di sottoclassare il mio MyDisposeableClass solo per taggare che ha bisogno di uno smaltimento esplicito, ma sembra abbastanza complicato, e sebbene funzioni in questo caso, ovviamente non funzionerebbe se volessi trattare con una classe sigillata.

C'è un modo migliore per farlo?

È stato utile?

Soluzione 2

Alla fine, utilizzo semplicemente parametri che accettano un tipo che racchiude MyDisposeable.La mia preoccupazione iniziale nel fare questo era che l'uso di un tipo interno per un parametro avrebbe avuto un impatto sull'accessibilità delle funzioni.(Forse avrebbe un impatto negativo sulla documentazione, ma in un cmdlet la documentazione è interamente controllata da un file XML.)

Dopo alcuni test, non sembrano esserci problemi nell'utilizzo di una classe interna per un parametro e nel lasciare che la trasformazione accetti tipi pubblici.Quindi creo semplicemente una classe wrapper:

public class MyDisposeableWrapper
{
    public MyDisposeable MyDisposeable
    {
        get;
        set;
    }

    public bool NeedsDisposed
    {
        get;
        set;
    }

    public MyDisposeableWrapper(MyDisposeable myDisposeable, bool needsDisposed)
    {
        MyDisposeable = myDisposeable;
        NeedsDisposed = needsDisposed;
    }
}

E lascia che il parametro prenda quello invece.Nell'attributo di trasformazione, imposta semplicemente NeedsDisposed in base al fatto che il parametro abbia preso un MyDisposeable o ne abbia costruito uno.ad esempio:

if(input is MyDisposeable)
{
    return new MyDisposeableWrapper((MyDisposeable) input, false);
}
else
{
    /* construct MyDisposeable from the input */
    return new MyDisposeableWrapper(myDisposeable, true);
}

Altri suggerimenti

Invece di creare sottoclassi, puoi aggiungere una proprietà alla tua classe MyDisposable?

public class MyDisposable
{
    ...   
    public bool IsAttributeCreated { get; set; }
}

Quindi nel codice dell'attributo

/* We created a MyDisposeable, we *should* dispose it */
return new MyDisposeable(input.ToString()){IsAttributeCreated=true};

Finalmente nel tuo blocco finale

finally
{
    /* Should only dispose MyDisposeable if we created it... */
    if (MyDisposable.IsAttributeCreated)
        MyDisposeable.Dispose();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top