2012-02-17 2 views
0

Как правило, я пытаюсь создать PSCmdlet, который принимает параметр типа, который реализует IDisposeable, и требует удаления во избежание утечки ресурсов. Я также хотел бы принять string для этого параметра и создать экземпляр этого типа, однако, если я сам создам этот объект, мне нужно будет его утилизировать до возвращения из ProcessRecord.Передача данных в PSCmdlet из его АргументTransformationAttribute

Я использую ArgumentTransformationAttribute с моим параметром для того, чтобы построить мой IDisposeable объект из строки, но я не могу найти способ передать данные из этого класса в моем PSCmdlet о создал ли я объект или нет. Например:

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

Моя догадка здесь подкласс мой MyDisposeableClass просто помечать, что она нуждается в явной утилизации, но это кажется довольно Hacky, и в то время как он работает в этом случае, очевидно, будет не если работать я хотел иметь дело с запечатанным классом.

Есть ли лучший способ сделать это?

ответ

0

В конце концов, я просто использовать параметры, которые принимают тип, который оборачивает MyDisposeable. Моя первоначальная забота об этом заключалась в том, что использование внутреннего типа для параметра повлияло бы на доступность функций. (Возможно, это негативно повлияет на документацию, но в командлете документация полностью контролируется XML-файлом.)

После некоторых тестов не возникает никаких проблем с использованием внутреннего класса для параметра и просто позволяя преобразования принимают общедоступные типы. Поэтому я просто создаю класс обертки:

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

    public bool NeedsDisposed 
    { 
     get; 
     set; 
    } 

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

И возьмите параметр вместо этого. В атрибуте преобразования просто установите NeedsDisposed в зависимости от того, принял ли параметр MyDisposeable или его построил. например:

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

Вместо того, чтобы подклассифицировать, можете ли вы добавить свойство в свой класс MyDisposable?

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

Затем в коде атрибута

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

Наконец в вашем наконец, блок

finally 
{ 
    /* Should only dispose MyDisposeable if we created it... */ 
    if (MyDisposable.IsAttributeCreated) 
     MyDisposeable.Dispose(); 
} 
+0

К сожалению, нет, в этом случае 'MyDisposeable' является библиотекой, которую я не могу изменить, за исключением некоторого отражения. –

 Смежные вопросы

  • Нет связанных вопросов^_^