Scott Harrison - The golden apples
Henry Parker's Robot Wars

ASP.Net, ADO, MS Access
C# How to use fluent Api to simplify interactions with complex processes

C# How to use fluent Api to simplify interactions with complex processes

(23 hits)
Hits=7 Fluent API makes your code more discoverable and much more easier to read. The complexity of the code is insulated in the concrete classes. Chaining methods is a helpful technique for understanding complex processes. In my code sample, I demonstrate how to create a Customer account. The customer account will use a login password was a data link. First, we create the address book, next we associated an email with the address book, then we create the customer record, and link the customer location address to the customer. Fluent API makes communication of what the object methods do more natural.

The ICustomerModule Interace only has one definition ICustomer Customer() which returns a fluentCustomer object. The self reference to ICustomer by the FluentCustomerModule allows chaining. FluentCustomerModule derives from ICustomerModule allowing chaining to Customer(). Once the fluentCustomer has been instantiated than we can access all of its chained methods.

Hits=5 The Customer Interface defines all the chain methods in the FluentCustomer concrete class. In this use case, I only deal with a cashpayment. The invoice Module was used to create the account receiveable from an invoice. The modules represent the useage of the fluent api concrete classes. If I need to create an accounts receivable entry without an invoice than I would add the fluentaccountreceivable class to the module.

Hits=6 The Unit of Work and its repository objects do all the entity frame work of creating, updating, deleting, and querying data from the database. The fluentCustomerQuery contains a set of collections of different types which can be loaded by parameter passing or by generic expressions invokes. I will demonstrate, how to use an lambda expression invoke to apply to a collection in my next sample. The ICustomerQuery Query() is defined in the FluentCustomer concrete class. It returns a ICustomerQuery type because the fluentCustomerQuery class is derived from ICustomerQuery. You now can chain the methods of the fluentCustomerQuery class which has the WithAccountsReceivable, WithCustomerLedgers, ..etc methods. I use property getters to access the collections of type T from the fluentCustomerQuery instance.

Customer Unit test


string json = "";


                json = @"{ ""CustomerName"":""Bob Smith"" 
                        ,""FirstName"":""Bob"",
                        ""LastName"":""Smith"",
                        ""CompanyName"":""BS Tech"",
                        
                        ""LocationAddress"":[{
                        ""Address_Line1"" : ""1111 11th Ave"",
                        ""City"" : ""Boise"",
                        ""State"" : ""ID"",
                        ""Zipcode"" : ""83709"",
                        ""Country"" : ""USA"",
                        ""Type"" : ""Primary""
                        }],
                        ""AccountEmail"":{
                              ""EmailText"" : ""bsmith@dc-tech.us"",
                              ""LoginEmail"" : true,
                              ""Password"" : ""12345""
                            }
                        }";
CustomerView customerView = JsonConvert.DeserializeObject<CustomerView>(json);

                CustomerModule custMod = new CustomerModule();

custMod
                    .Customer()

                        .CreateAddressBook(customerView)
                        .Apply()
                        .CreateCustomerEmail(customerView)
                        .Apply()
                        .CreateCustomer(customerView)
                        .Apply()
                        .CreateCustomerLocationAddress(customerView)
                        .Apply()
                        ;


ICustomerModule interface

 public interface ICustomerModule
    {
        ICustomer Customer();
    }
    public class CustomerModule : AbstractModule, ICustomerModule
    {
        private FluentCustomer _Customer;
        public ICustomer Customer()
        {
            _Customer = new FluentCustomer();
            return _Customer as ICustomer;
        }

        public IList<AccountReceiveableView> AccountReceivableViews { get { return _Customer._query.listAccountsReceivableViews; } }
        public IList<CustomerLedgerView> CustomerLedgerViews { get { return _Customer._query.listCustomerLedgerViews; } }
        public IList<EmailView> EmailViews { get { return _Customer._query.listEmailViews; } }
        public IList<PhoneView> PhoneViews { get { return _Customer._query.listPhoneViews; } }
        public IList<InvoiceView> InvoiceViews { get { return _Customer._query.listInvoiceViews; } }
        public IList<ScheduleEventView> ScheduleEventViews { get { return _Customer._query.listScheduleEventViews; } }
        public IList<LocationAddressView> LocationAddressViews { get { return _Customer._query.listLocationAddressViews; } }
        public IList<CustomerClaimView> CustomerClaimViews { get { return _Customer._query.listCustomerClaimViews; } }
        public IList<ContractView> ContractViews { get { return _Customer._query.listContractViews; } }
    }

Customer Interface


    public interface ICustomer
    {
        ICustomer CreateAddressBook(CustomerView customerView);
        ICustomer CreateCustomerLocationAddress(CustomerView customerView);
        ICustomer CreateCustomer(CustomerView customerView);
        ICustomer CreateCustomerEmail(CustomerView customerView);
        ICustomer Apply();
        ICustomerQuery Query();
    }

FluentCustomer concrete class


 public abstract class AbstractModule
    {
        public string GetMyMethodName()
        {
            var st = new StackTrace(new StackFrame(1));
            return st.GetFrame(0).GetMethod().Name;
        }
    }


 public class FluentCustomer : AbstractModule, ICustomer
    {
        public UnitOfWork unitOfWork = new UnitOfWork();
        CreateProcessStatus processStatus;
        public FluentCustomerQuery _query;


        public ICustomerQuery Query()
        {
            _query = new FluentCustomerQuery();
            return _query as ICustomerQuery;
        }

        public ICustomer CreateCustomerEmail(CustomerView customerView)
        {
            Task<AddressBook> lookupAddressBookTask = Task.Run(() => unitOfWork.addressBookRepository.GetAddressBookByCustomerView(customerView));
            Task.WaitAll(lookupAddressBookTask);
            customerView.AddressId = lookupAddressBookTask.Result.AddressId;

            if (customerView.AddressId > 0)
            {
                EmailView emailView = new EmailView();
                emailView.AddressId = customerView.AddressId;
                emailView.EmailText = customerView.AccountEmail.EmailText;
                emailView.LoginEmail = customerView.AccountEmail.LoginEmail;
                emailView.Password = customerView.AccountEmail.Password;

                Task<CreateProcessStatus> resultTask = Task.Run(() => unitOfWork.emailRepository.CreateEmail(emailView));
                processStatus = resultTask.Result;
            }
            else
            {
                processStatus = CreateProcessStatus.Failed;
            }

            return this as ICustomer;
        }
        public ICustomer CreateCustomer(CustomerView customerView)
        {
            try
            {
                Task<AddressBook> lookupAddressBookTask = Task.Run(() => unitOfWork.addressBookRepository.GetAddressBookByCustomerView(customerView));
                Task.WaitAll(lookupAddressBookTask);
                customerView.AddressId = lookupAddressBookTask.Result.AddressId;


                Task<CreateProcessStatus> resultTask = Task.Run(() => unitOfWork.customerRepository.CreateCustomer(customerView));
                Task.WaitAll(resultTask);

                processStatus = resultTask.Result;

                return this as ICustomer;

            }
            catch (Exception ex)
            {
                throw new Exception(GetMyMethodName(), ex);
            }
        }
        public ICustomer CreateCustomerLocationAddress(CustomerView customerView)
        {
            Task<AddressBook> lookupAddressBookTask = Task.Run(() => unitOfWork.addressBookRepository.GetAddressBookByCustomerView(customerView));
            Task.WaitAll(lookupAddressBookTask);

            customerView.AddressId = lookupAddressBookTask.Result.AddressId;

            Task<CreateProcessStatus> resultTask = Task.Run(() => unitOfWork.locationAddressRepository.CreateLocationUsingCustomer(customerView));
            Task.WaitAll(resultTask);

            return this as ICustomer;

        }
        public ICustomer CreateAddressBook(CustomerView customerView)
        {

            Task<CreateProcessStatus> statusTask = Task.Run(() => unitOfWork.addressBookRepository.CreateAddressBook(customerView));
            Task.WaitAll(statusTask);
            processStatus = statusTask.Result;
            return this as ICustomer;
        }
        public ICustomer Apply()
        {
            if ((processStatus == CreateProcessStatus.Inserted) || (processStatus == CreateProcessStatus.Updated) || (processStatus == CreateProcessStatus.Deleted))
            {
                unitOfWork.CommitChanges();
            }
            return this as ICustomer;

        }

    }

FluentCustomerQuery Query()


   custMod
               .Customer()
               .Query()
                   .WithAccountReceivables(customerId);

            IList<AccountReceiveableView> list = custMod.AccountReceivableViews;

ICustomerQuery

public interface ICustomerQuery

    {

        ICustomerQuery WithAccountReceivables(long customerId);
        ICustomerQuery WithCustomerLedgers(long customerId);
        ICustomerQuery WithEmails(long customerId);
        ICustomerQuery WithPhones(long customerId);
        ICustomerQuery WithInvoices(long customerId, long? invoiceId);
        ICustomerQuery WithScheduleEvent(long customerId, long serviceId);
        ICustomerQuery WithLocationAddress(long customerId);
        ICustomerQuery WithCustomerClaims(long customerId);
        ICustomerQuery WithContracts(long customerId, long contractId);
    }
  public class FluentCustomerQuery : FluentCustomer, ICustomerQuery
    {
        public IList<AccountReceiveableView> listAccountsReceivableViews;
        public IList<CustomerLedgerView> listCustomerLedgerViews;
        public IList<EmailView> listEmailViews;
        public IList<PhoneView> listPhoneViews;
        public IList<InvoiceView> listInvoiceViews;
        public IList<ScheduleEventView> listScheduleEventViews;
        public IList<LocationAddressView> listLocationAddressViews;
        public IList<CustomerClaimView> listCustomerClaimViews;
        public IList<ContractView> listContractViews;

        public FluentCustomerQuery()
        {
            listAccountsReceivableViews = new List<AccountReceiveableView>();
            listCustomerLedgerViews = new List<CustomerLedgerView>();
            listEmailViews = new List<EmailView>();
            listPhoneViews = new List<PhoneView>();
            listInvoiceViews = new List<InvoiceView>();
            listScheduleEventViews = new List<ScheduleEventView>();
            listLocationAddressViews = new List<LocationAddressView>();
            listCustomerClaimViews = new List<CustomerClaimView>();
            listContractViews = new List<ContractView>();
        }
        public ICustomerQuery WithAccountReceivables(long customerId)
        {
            try
            {
                listAccountsReceivableViews = base.unitOfWork.customerRepository.GetAccountReceivablesByCustomerId(customerId);
                return this as ICustomerQuery;
            }
            catch (Exception ex)
            {
                throw new Exception(GetMyMethodName(), ex);
            }
        }
        public ICustomerQuery WithCustomerLedgers(long customerId)
        {
            try
            {
                listCustomerLedgerViews = base.unitOfWork.customerRepository.GetCustomerLedgersByCustomerId(customerId);
                return this as ICustomerQuery;
            }
            catch (Exception ex)
            {
                throw new Exception(GetMyMethodName(), ex);
            }
        }


        public ICustomerQuery WithEmails(long customerId)
        {
            try
            {
                listEmailViews = base.unitOfWork.customerRepository.GetEmailsByCustomerId(customerId);
                return this as ICustomerQuery;
            }
            catch (Exception ex) { throw new Exception(GetMyMethodName(), ex); }
        }

        public ICustomerQuery WithPhones(long customerId)
        {
            try
            {
                listPhoneViews = base.unitOfWork.customerRepository.GetPhonesByCustomerId(customerId);
                return this as ICustomerQuery;
            }
            catch (Exception ex) { throw new Exception(GetMyMethodName(), ex); }
        }

        public ICustomerQuery WithInvoices(long customerId, long? invoiceId)
        {
            try
            {
                listInvoiceViews = base.unitOfWork.customerRepository.GetInvoicesByCustomerId(customerId, invoiceId);
                return this as ICustomerQuery;
            }
            catch (Exception ex) { throw new Exception(GetMyMethodName(), ex); }
        }
        public ICustomerQuery WithScheduleEvent(long customerId, long serviceId)
        {
            try
            {
                listScheduleEventViews = base.unitOfWork.customerRepository.GetScheduleEventsByCustomerId(customerId, serviceId);
                return this as ICustomerQuery;
            }
            catch (Exception ex) { throw new Exception(GetMyMethodName(), ex); }
        }
        public ICustomerQuery WithLocationAddress(long customerId)
        {
            try
            {
                listLocationAddressViews = base.unitOfWork.customerRepository.GetLocationAddressByCustomerId(customerId);
                return this as ICustomerQuery;
            }
            catch (Exception ex) { throw new Exception(GetMyMethodName(), ex); }
        }

        public ICustomerQuery WithCustomerClaims(long customerId)
        {
            try
            {
                listCustomerClaimViews = base.unitOfWork.customerRepository.GetCustomerClaimsByCustomerId(customerId);
                return this as ICustomerQuery;
            }
            catch (Exception ex) { throw new Exception(GetMyMethodName(), ex); }
        }
        public ICustomerQuery WithContracts(long customerId, long contractId)
        {
            try
            {
                listContractViews = base.unitOfWork.customerRepository.GetContractsByCustomerId(customerId, contractId);
                return this as ICustomerQuery;
            }
            catch (Exception ex) { throw new Exception(GetMyMethodName(), ex); }
        }
    }
....

...<<<Register to correspond>>> ...

Members : 152
Name:
Email:

Register to View

Help