Eu me deparei com este problema: #24898
: MemberwiseClone está faltando após a atualização para o PowerShell 7.5.0 :
class MyClass {
[string]$Name
[object] CloneProblem() {
return $this.MemberwiseClone()
}
}
$obj = [MyClass]::new()
$obj.CloneProblem()
InvalidOperation: Linha | 6 | return $this.MemberwiseClone() # Falha com "não contém … | ~~~~~~~~~~~~~~~~~~~~~~~ | A invocação do método falhou porque [MyClass] não contém um método chamado 'MemberwiseClone'.
Qual seria a solução alternativa mais concisa e/ou eficiente para criar uma alternativa ao método de cópia superficial do PowerShell , levando em consideração que a classe em questão pode ter vários derivados, MyClass1 : MyClass { }
o que significa que não quero o tipo de classe codificado no método em questão?
O mais rápido é criar o novo objeto codificando todos os membros existentes.
A maneira mais concisa, mas menos eficiente, se o tipo tiver muitos membros, é enumerar as propriedades que acessam
PSObject
o membro.Alternativamente, se você não quiser codificar o tipo na
return
declaração, você pode usarLanguagePrimitives.ConvertTo
:Outro método menos eficiente é invocar
MemberwiseClone
via reflexão, idealmenteMethodInfo
deve ser armazenado em cache em umstatic
campo.Uma continuação da abordagem anterior, provavelmente exagerada, já que a abordagem anterior deveria ser suficiente em todos os casos possíveis, pode ser armazenar
Func<>
delegados em um dicionário estático para cada derivado.Para complementar a resposta útil de Santiago , que mostra diversas técnicas úteis:
A solução mais concisa - mas não tão eficiente - é usar reflexão em cada invocação :
Como observa a resposta de Santiago, para uma solução de alto desempenho , você precisa armazenar em cache a definição do método obtida por meio de reflexão para evitar o impacto no desempenho que a reflexão acarreta.
Para fazer isso, você pode aproveitar o fato de poder usar
::
, o operador de acesso a membros estáticos , diretamente na variável automática$this
que representa a instância de classe em questão.Isso não é apenas mais conveniente do que ter que repetir o nome da classe na forma de um literal de tipo (
[MyClass]
), mas também evita o problema de codificar o tipo de retorno, o que atrapalharia a subclassificação (derivação) da sua classe.