Pergunta

Eu tenho uma classe com várias propriedades parecidas com estas:

public string Name
{
    get { return _name; }
    set { IsDirty = true; _name = value; }
}

Seria muito mais fácil se eu pudesse confiar no C# 3.0 para gerar o armazenamento de apoio para eles, mas existe alguma maneira de fatorar o IsDirty=true;para que eu possa escrever minhas propriedades mais ou menos assim e ainda obter o mesmo comportamento:

[MakesDirty]
public string Name { get; set; }
Foi útil?

Solução

Não.Não sem escrever consideravelmente mais código (arcano?) Do que a versão original (Você teria que usar reflexão para verificar o atributo na propriedade e quais não.eu mencionei que é 'mais lento').Este é o tipo de duplicação com a qual posso conviver.

MS tem a mesma necessidade de gerando eventos quando uma propriedade é alterada.INotifyPropertyChanged que é uma interface vital para notificações de alterações.Toda implementação que eu já vi ainda

set
{ 
  _name = value; 
  NotifyPropertyChanged("Name"); 
}

Se fosse possível, imagino que aqueles caras espertos da MS já teriam algo assim em vigor.

Outras dicas

Você pode tentar configurar um trecho de código para facilitar sua criação.

Se você realmente quer seguir esse caminho, modificar o que o código faz usando um atributo, existem algumas maneiras de fazer isso e todas estão relacionadas ao AOP (programação orientada a aspectos).Confira PostSharp, que é um pós-compilador que pode modificar seu código em uma etapa pós-compilação.Por exemplo, você pode configurar um atributo personalizado para suas propriedades (ou aspecto, como é chamado no AOP) que injeta código dentro dos configuradores de propriedades, que marca seus objetos como sujos.Se você quiser alguns exemplos de como isso é conseguido, você pode conferir seus tutoriais.

Mas tenha cuidado com o AOP e porque você pode facilmente criar mais problemas com ele do que está tentando resolver se não for usado corretamente.

Existem mais estruturas AOP por aí, algumas usando pós-compilação e outras usando mecanismos de interceptação de métodos que estão presentes no .Net; as últimas apresentam algumas desvantagens de desempenho em comparação com as primeiras.

Não, ao usar propriedades automáticas você não tem nenhum controle sobre a implementação.A melhor opção é usar uma ferramenta de modelagem, trechos de código ou criar um SetValue privado<T>(ref T backingField, T value) que encapsula a lógica do setter.

private void SetValue<T>(ref T backingField, T value)
{
   if (backingField != value)
   {
      backingField = value;
      IsDirty = true;
   }
}

public string Name
{
   get
   {
      return _name;
   }
   set
   {
      SetValue(ref _name, value);
   }
}

A outra alternativa pode ser um gerador de código como o codesmith para automatizar a criação das propriedades.Isto seria especialmente útil se as propriedades que você está criando forem colunas em uma tabela de banco de dados

Eu posso recomendar usar Biblioteca Empresarial para aquele propósito.O Policy Application Block fornece a infraestrutura para fazer "alguma coisa" (alguma coisa = você pode codificar isso sozinho) sempre que entrar/sair de um método, por exemplo.Você pode controlar o comportamento com atributos.Tome isso como uma dica e entre em detalhes com a documentação da biblioteca corporativa.

Há um DefaultValueAttribute que pode ser atribuído a uma propriedade, ele é usado principalmente pelas ferramentas de designer para que possam indicar quando uma propriedade foi alterada, mas pode ser uma maneira "organizada" de descrever qual é o valor padrão de uma propriedade. , e assim poder identificar se foi alterado.

Você precisaria usar o Reflection para identificar alterações nas propriedades - o que na verdade não é que caro, a menos que você esteja fazendo muito isso!

Embargo:Você não seria capaz de saber se uma propriedade foi alterada VOLTAMENTE de um valor não padrão para o padrão.

Eu diria que a melhor maneira de resolver isso é usar a Programação Orientada a Aspectos (AOP).Mats Helander fez um escreva sobre isso no InfoQ.O artigo está um pouco confuso, mas é possível acompanhar.Existem vários produtos diferentes que fazem AOP no espaço .NET, eu recomendo o PostSharp.

Se você escolher Atributos, tenho quase certeza de que terá que role sua própria lógica para deduzir o que significam e o que fazer com eles.O que quer que esteja usando seus objetos de classe personalizados terá que ter uma maneira de executar essas ações/verificações de atributos, de preferência na instanciação.

Caso contrário, você está pensando em usar eventos talvez.Você ainda teria que adicionar o evento a cada método set, mas o benefício seria que você não codificaria o que fazer com conjuntos sujos em todas as propriedades e poderia controlar, em um só lugar, o que deve ser feito.Isso introduziria, no mínimo, um pouco mais de reutilização de código.

Objeto ContextBound.Se você criar uma classe que estenda o objeto vinculado ao contexto e criar um ContextAttribute, poderá interceptar as chamadas feitas para essa propriedade e definir o IsDirty.O .NET criará um proxy para sua classe para que todas as chamadas passem por algo como um coletor remoto.

O problema com essa abordagem é que seu proxy só será invocado quando chamado externamente.Vou te dar um exemplo.

class A
{
    [Foo]
    public int Property1{get; set;}
    public int Property2{get {return variable;} set{ Property1 = value; variable = value; }
}

Quando property1 for chamado de outra classe, seu proxy será invocado.Mas se outra classe chamar a propriedade2, mesmo que o conjunto de propriedades2 chame a propriedade1, nenhum proxy será invocado (um proxy não é necessário quando você está na própria classe).

Há muitos exemplos de código sobre o uso de ContextBoundObjects, dê uma olhada neles.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top