Obter todos os objects associados / compostos dentro de um object (na maneira abstrata)

Negócio :

Eu tenho um sistema de pagamento no qual o pagamento pode ser feito através da GiftCoupon, ClubMembershipCard, etc. Um pagamento em si pode ter múltiplos componentes de pagamento

Classe :

Eu tenho uma class de pagamento. Tem componentes de pagamento como GiftCouponPayment, ClubMembershipCardPayment, CashPayment e assim por diante. Cada tipo de componente satisfaz uma interface comum IPaymentComponent. Eu o implementei usando o conhecimento sobre os tipos existentes.

Questões

1) Como implementar esta function de forma abstrata – sem saber quais são todos os tipos que existem? Isso significa que precisa trabalhar para todos os tipos que implementam a interface IPaymentComponent.

2) Se não for possível alcançá-lo no LINQ to SQL, é possível no Entity Framework?

3) É associação / agregação ou composição quando o LINQ to SQL gera entidades GiftCouponPayment dentro do object Payment?

Nota: Estou usando o LINQ to SQL como ORM. GiftCouponPayment e Payment são classs autogeradas e esses objects são criados pelo ORM. Eu adicionei mais funcionalidade a essas classs usando classs parciais.

Observação: no database, cada PaymentComponent (por exemplo, GiftCouponPayment) tem suas próprias propriedades (por exemplo, CouponValue, CardValue etc). Portanto, a tabela por hierarquia não será boa . Precisamos de tabelas separadas. Existe uma solução nessa linha?

Nota: GiftCouponPayment já existe no database antes deste pagamento. Precisamos identificar o object GiftCouponPayment usando o GiftCouponPaymentID fornecido pelo cliente. Precisamos apenas atualizar a coluna PaymentID nessa tabela.

Uma abstração gotejante se refere a qualquer abstração implementada, destinada a reduzir (ou ocultar) a complexidade, onde os detalhes subjacentes não estão completamente ocultos.

Diagrama LINQ para SQL

insira a descrição da imagem aqui

REFERÊNCIA :

  1. Entidade Framework 4, herdando vs estendendo?
  2. Como escolher uma estratégia de inheritance http://blogs.msdn.com/b/alexj/archive/2009/04/15/tip-12-choosing-an-inheritance-strategy.aspx
  3. Amostras da Fluent API – http://blogs.msdn.com/b/adonet/archive/2010/12/14/ef-feature-ctp5-fluent-api-samples.aspx

C # CODE

public interface IPaymentComponent { int MyID { get; set; } int MyValue { get; set; } int GetEffectiveValue(); } public partial class GiftCouponPayment : IPaymentComponent { public int MyID { get { return this.GiftCouponPaymentID; } set { this.GiftCouponPaymentID = value; } } public int MyValue { get { return this.CouponValue; } set { this.CouponValue = value; } } public int GetEffectiveValue() { if (this.CouponNumber < 2000) { return 0; } return this.CouponValue; } } public partial class Payment { public List AllPaymentComponents() { List allPayComps = new List(); List giftCouponPaymentList = new List(); List cashPaymentList = new List(); foreach (GiftCouponPayment g in this.GiftCouponPayments) { giftCouponPaymentList.Add(g); allPayComps.Add(g); } foreach (CashPayment c in this.CashPayments) { cashPaymentList.Add(c); allPayComps.Add(c); } return allPayComps; } } 

Eu acho que você pode querer recuar do design por um momento. O que eu ouvi é isto:

Um pagamento consiste em um ou mais componentes, e cada componente pode ser de vários tipos

O que parece que você precisa é uma tabela de Payment , em seguida, uma tabela PaymentComponent com uma relação de chave estrangeira para a tabela Payment . Você pode então implementar inheritance na tabela PaymentComponent para suas várias formas de pagamento.

Você pode tentar usar uma camada de abstração ou uma camada de access de dados que será genérica do tipo T. Ou, pelo menos, tornar os methods genéricos.

Você basicamente tem alguns problemas aqui:

  1. Como modelar os tipos de pagamento

    Vamos supor que queremos ir a este modo clássico de OOP:

    Você precisa de uma class base, pagamento (ou PaymentBase), que é abstrato e várias classs que herdam dele, por exemplo, PaymentInCash, PaymentWithCreditCard e etc.

    Uma alternativa poderia ser adicionar PaymentDetails to Payment e criar uma hierarquia de PaymentDetails. Se você optar por fazer isso, substitua Payment with PaymentDetails em todos os pontos a seguir.

    Para pagamentos com vários methods , você poderia:

    uma. Tenha uma coleção de PaymentDetails sob um pagamento
    ou
    b. Crie um tipo chamado AggregatePayment, que tem uma lista de pagamentos.

  2. Como mapear os tipos de pagamento para tabelas

    Tanto o TPT quanto o TPH são válidos aqui …

    Para TPT use uma tabela para pagamento e uma tabela para cada tipo de pagamento.
    Todas as tabelas PK’s do tipo herdado devem ser um FK para a tabela do tipo base.
    Se você tem múltiplos níveis de hierarquia, você pode usar TPT ou TPH no segundo nível (ou qualquer outro) se estiver usando o EF.

    Para o TPH, use uma tabela com uma coluna discriminadora (por exemplo, PaymentType) e marque cada coluna que não é compartilhada entre todas as entidades na hierarquia como anulável. Não use a mesma coluna para propriedades diferentes em entidades diferentes. No EF, mapear cada entidade para a mesma tabela com a condição PaymentType = (o número vai aqui) e (nome (s) da coluna que não deve ser nulo) não é nulo.

    Minha recomendação é que, se você tiver muitos tipos restritos (poucas propriedades cada), vá com o TPH, se você tiver alguns tipos grandes, vá com o TPT.

  3. Qual técnica de padrão / código de design a ser usada para o algoritmo de pagamento

    Você tem mais opções aqui:

    uma. Use classs parciais e coloque um método ProcessPayment () abstrato na class base e sobrescreva nas classs herdadas.

    b. Use uma class PaymentProcessor base e um PaymentProcessor específico por tipo de pagamento, por exemplo, PaymentInCashProcessor. Nesse método, você pode usar a reflection para carregar o tipo correto do PaymentProcessor, armazenando um dictionay ou, melhor ainda, usando genéricos:

 abstract class PaymentProcessor { } abstract class PaymentProcessor : PaymentProcessor where TPayment : class, Payment { } class PaymentInCashProcessor : PaymentProcessor { } // Use reflection to find types that inherits from PaymentProcessor // create an instance of the type you found // then cast the instance to PaymentProcessor to use 

Se você projetar seu modelo EF, poderá usar a propriedade abstrata em uma class básica chamada pagamento. E vamos herdar todos os seus tipos de pagamento dessa class:

Modelo do Entity Framework

O pagamento terá todas as propriedades comuns e cada tipo específico pode ter suas próprias propriedades.

Se você tiver esse tipo de modelo, basta consultar os pagamentos.

Isso retorna todos os objects que herdam o tipo de pagamento:

 var allPayments = objectContext.Payments;