Question

En général, je suis en train de créer une PSCmdlet qui prend un paramètre d'un type qui implémente IDisposeable et nécessite disposition afin d'éviter les ressources qui fuient. Je voudrais aussi que d'accepter un string pour ce paramètre et créer une instance de ce type, si je crée cet objet moi-même, je dois disposer avant de revenir de ProcessRecord.

J'utilise un ArgumentTransformationAttribute avec mon paramètre pour construire mon objet IDisposeable d'une chaîne, mais je ne peux pas trouver un moyen de transmettre des données de cette classe à mon PSCmdlet de savoir si je crée l'objet ou non. Par exemple:

[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());
    }
}

Ma meilleure estimation est ici sous-classe mon MyDisposeableClass juste pour étiquette dont il a besoin disposition explicite, mais qui semble assez hacky, et tout cela fonctionne dans ce cas, il ne serait évidemment pas le travail si je voulais faire face à une classe scellée .

Y at-il une meilleure façon de le faire?

Était-ce utile?

La solution 2

En fin de compte, j'utilise simplement les paramètres qui acceptent un type qui enveloppe MyDisposeable. Ma première préoccupation à faire était que l'utilisation d'un type interne pour un paramètre aurait une incidence sur l'accessibilité des fonctions. (Peut-être qu'il aurait un impact négatif sur la documentation, mais dans une cmdlet la documentation est entièrement contrôlée par un fichier XML.)

Après quelques essais, il ne semble pas être un problème en utilisant une classe interne pour un paramètre et juste laisser la transformation accepter les types publics. Je crée donc simplement une classe d'emballage:

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

    public bool NeedsDisposed
    {
        get;
        set;
    }

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

Et que la prise de paramètre à la place. Dans l'attribut de transformation, il suffit de définir NeedsDisposed sur la base de savoir si le paramètre a une MyDisposeable ou construit une. par exemple:

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

Autres conseils

Au lieu de sous-classement, vous pouvez ajouter une propriété à votre classe MyDisposable?

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

Ensuite, dans votre code d'attribut

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

Enfin, dans votre bloc finally

finally
{
    /* Should only dispose MyDisposeable if we created it... */
    if (MyDisposable.IsAttributeCreated)
        MyDisposeable.Dispose();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top