0

I would like to pass a class type as a parameter so it can use a share method to do similar jobs.

At first, processContact will be call and do the following, there will be more and more similar method like ProcessGeneralAccountContact,ProcessOperationalIntegrityAccountContact and ProcessPaAccountContact, they are just updating/creating records in different Accounts. Every of them has a individual Process,Create and Update process, I would like to create a share method for processes.

e.g.

I can call create/update all contact by just doing this

        ProcessContact(sourceContact, GeneralAccountManager, GeneralAccountField, GeneralAccountFieldAttribute),
        ProcessContact(sourceContact, PaAccountManager,PaAccountField,PaAccountFieldAttribute),
        ProcessContact(sourceContact,HrAccountManager,HrAccountField,HrAccountFieldAttribute),

Is it possible to pass a class type like Process(sourceContact,typeof(GeneralAccountManager),typeof(GeneralAccountField),typeof(GeneralAccountFieldAttribute)) to add flexibility to the code to avoid code repetition?

Thanks so much guys!

using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Web.Http;
using System.Web.Script.Serialization;
using ClientProject.Common.Api;
using u2ool.Data;
using u2ool.Logging;
using WebhookApiUpdater.Infrastructure;
using WebhookApiUpdater.Models;

namespace WebhookApiUpdater.Controllers
{
    public class UpdateController : ApiController
    {
        [HttpPost]
        public HttpStatusCode Record()
        {
            var sourceContact = GetSourceModel(Request);
            return ProcessContact(sourceContact);
        }


    private HttpStatusCode ProcessContact(ContactModel sourceContact)
    {
        List<HttpStatusCode> returnedHttpStatusCodes = new List<HttpStatusCode>
        {   // each of the account has to be processed separately as the Managers are unique and have no common denominator class 
            ProcessGeneralAccountContact(sourceContact),
            ProcessOperationalIntegrityAccountContact(sourceContact),
            ProcessPaAccountContact(sourceContact),
            ProcessInternalCommsProjectsContact(sourceContact),
            ProcessEaAccountContact(sourceContact),
            ProcessHrAccountContact(sourceContact)
            //this is what I want to do 
            Process(sourceContact,typeof(GeneralAccountManager),typeof(GeneralAccountField),typeof(GeneralAccountFieldAttribute))
        };

        return returnedHttpStatusCodes.All(x => x == HttpStatusCode.Accepted)
            ? HttpStatusCode.Accepted
            : returnedHttpStatusCodes.FirstOrDefault(x => x != HttpStatusCode.Accepted);
    }

    private HttpStatusCode Process(ContactModel sourceContact, Type accountManager,Type accountField, Type accountFieldAttribute)
    {
        var currentAccountManager = Activator.CreateInstance(accountManager);
        Enum currentAccountField = (Enum)Enum.ToObject(accountField,accountField);
        var currentAccountFieldAttribute = Activator.CreateInstance(accountFieldAttribute);

        ((Manager<currentAccountField, currentAccountFieldAttribute>)currentAccountManager).data

        var generalAccountContact = GeneralAccountManager.Database.QueryContacts<ContactModel>(GeneralAccountFilter.Eq(GeneralAccountField.EmployeeID, sourceContact.EmployeeID), 1).ToList();

        if (generalAccountContact.Count == 0 || generalAccountContact.First().ReferenceID == Guid.Empty)
            return CreateGeneralAccountContact(sourceContact);
        // else
        sourceContact.ReferenceID = generalAccountContact.First().ReferenceID;
        return UpdateGeneralAccountContact(sourceContact);
    }
     private HttpStatusCode ProcessHrAccountContact(ContactModel sourceContact)
    {
        var hrAccountContact = HrAccountManager.Database.QueryContacts<ContactModel>(HrAccountFilter.Eq(HrAccountField.EmployeeID, sourceContact.EmployeeID), 1).ToList();

        if (hrAccountContact.Count == 0 || hrAccountContact.First().ReferenceID == Guid.Empty)
            return CreateHrAccountContact(sourceContact);
        // else
        sourceContact.ReferenceID = hrAccountContact.First().ReferenceID;
        return UpdateHrAccountContact(sourceContact);
    }

    private HttpStatusCode ProcessEaAccountContact(ContactModel sourceContact)
    {
        var eaAccountContact = EaAccountManager.Database.QueryContacts<ContactModel>(EaAccountFilter.Eq(EaAccountField.EmployeeID, sourceContact.EmployeeID), 1).ToList();

        if (eaAccountContact.Count == 0 || eaAccountContact.First().ReferenceID == Guid.Empty)
            return CreateEaAccountContact(sourceContact);
        // else
        sourceContact.ReferenceID = eaAccountContact.First().ReferenceID;
        return UpdateEaAccountContact(sourceContact);
    }

    private HttpStatusCode ProcessInternalCommsProjectsContact(ContactModel sourceContact)
    {
        var internalCommsProjectsContact = InternalCommsProjectsAccountManager.Database.QueryContacts<ContactModel>(InternalCommsProjectsAccountFilter.Eq(InternalCommsProjectsAccountField.EmployeeID, sourceContact.EmployeeID), 1).ToList();

        if (internalCommsProjectsContact.Count == 0 || internalCommsProjectsContact.First().ReferenceID == Guid.Empty)
            return CreateInternalCommsProjectsContact(sourceContact);
        // else
        sourceContact.ReferenceID = internalCommsProjectsContact.First().ReferenceID;
        return UpdateInternalCommsProjectsContact(sourceContact);
    }

    private HttpStatusCode ProcessGeneralAccountContact(ContactModel sourceContact)
    {
        var generalAccountContact = GeneralAccountManager.Database.QueryContacts<ContactModel>(GeneralAccountFilter.Eq(GeneralAccountField.EmployeeID, sourceContact.EmployeeID), 1).ToList();

        if (generalAccountContact.Count == 0 || generalAccountContact.First().ReferenceID == Guid.Empty)
            return CreateGeneralAccountContact(sourceContact);
        // else
        sourceContact.ReferenceID = generalAccountContact.First().ReferenceID;
        return UpdateGeneralAccountContact(sourceContact);
    }

    private HttpStatusCode ProcessOperationalIntegrityAccountContact(ContactModel sourceContact)
    {
        var operationalIntegrityAccountContact = OperationalIntegrityAccountManager.Database.QueryContacts<ContactModel>(OperationalIntegrityAccountFilter.Eq(OperationalIntegrityAccountField.EmployeeID, sourceContact.EmployeeID), 1).ToList();

        if (operationalIntegrityAccountContact.Count == 0 || operationalIntegrityAccountContact.First().ReferenceID == Guid.Empty)
            return CreateOperationalIntegrityAccountContact(sourceContact);
        // else
        sourceContact.ReferenceID = operationalIntegrityAccountContact.First().ReferenceID;
        return UpdateOperationalIntegrityAccountContact(sourceContact);
    }

    private HttpStatusCode ProcessPaAccountContact(ContactModel sourceContact)
    {
        var paAccountContact = PaAccountManager.Database.QueryContacts<ContactModel>(PaAccountFilter.Eq(PaAccountField.EmployeeID, sourceContact.EmployeeID), 1).ToList();

        if (paAccountContact.Count == 0 || paAccountContact.First().ReferenceID == Guid.Empty)
            return CreatePaAccountContact(sourceContact);
        // else
        sourceContact.ReferenceID = paAccountContact.First().ReferenceID;
        return UpdatePaAccountContact(sourceContact);
    }

    private HttpStatusCode UpdateGeneralAccountContact(ContactModel sourceContact)
    {
        Action<ContactModel> generalAccountUpdateAction = update => GeneralAccountManager.Database.UpdateContact(sourceContact.ReferenceID, sourceContact);
        return UpdateContact(generalAccountUpdateAction, sourceContact);
    }
    private HttpStatusCode UpdateOperationalIntegrityAccountContact(ContactModel sourceContact)
    {
        Action<ContactModel> operationalIntegrityUpdateAction = update => OperationalIntegrityAccountManager.Database.UpdateContact(sourceContact.ReferenceID, sourceContact);
        return UpdateContact(operationalIntegrityUpdateAction, sourceContact);
    }
    private HttpStatusCode UpdatePaAccountContact(ContactModel sourceContact)
    {
        Action<ContactModel> paAccountUpdateAction = update => PaAccountManager.Database.UpdateContact(sourceContact.ReferenceID, sourceContact);
        return UpdateContact(paAccountUpdateAction, sourceContact);
    }

    private HttpStatusCode UpdateInternalCommsProjectsContact(ContactModel sourceContact)
    {
        Action<ContactModel> internalCommsProjectsAccountAction = update => InternalCommsProjectsAccountManager.Database.UpdateContact(sourceContact.ReferenceID, sourceContact);
        return UpdateContact(internalCommsProjectsAccountAction, sourceContact);
    }

    private HttpStatusCode UpdateEaAccountContact(ContactModel sourceContact)
    {
        Action<ContactModel> eaAccountAccountUpdateAction = update => EaAccountManager.Database.UpdateContact(sourceContact.ReferenceID, sourceContact);
        return UpdateContact(eaAccountAccountUpdateAction, sourceContact);
    }

    private HttpStatusCode UpdateHrAccountContact(ContactModel sourceContact)
    {
        Action<ContactModel> hrAccountAccountUpdateAction = update => HrAccountManager.Database.UpdateContact(sourceContact.ReferenceID, sourceContact);
        return UpdateContact(hrAccountAccountUpdateAction, sourceContact);
    }

    private HttpStatusCode UpdateContact(Action<ContactModel> dbUpdateAction, ContactModel sourceContact)
    {
        try
        {
            dbUpdateAction(sourceContact);
            return HttpStatusCode.Accepted;
        }
        catch (Exception e)
        {
            Log.Exception(e);
            return HttpStatusCode.InternalServerError;
        }
    }

    private HttpStatusCode CreateGeneralAccountContact(ContactModel sourceContact)
    {
        Action<ContactModel> generalAccountCreateAction = create => GeneralAccountManager.Database.AddContact(sourceContact);
        return CreateContact(generalAccountCreateAction, sourceContact);
    }
    private HttpStatusCode CreateOperationalIntegrityAccountContact(ContactModel sourceContact)
    {
        Action<ContactModel> operationalIntegrityAccountCreateAction = create => OperationalIntegrityAccountManager.Database.AddContact(sourceContact);
        return CreateContact(operationalIntegrityAccountCreateAction, sourceContact);
    }
    private HttpStatusCode CreatePaAccountContact(ContactModel sourceContact)
    {
        Action<ContactModel> paAccountManagerCreateAction = create => PaAccountManager.Database.AddContact(sourceContact);
        return CreateContact(paAccountManagerCreateAction, sourceContact);
    }
    private HttpStatusCode CreateInternalCommsProjectsContact(ContactModel sourceContact)
    {
        Action<ContactModel> internalCommsProjectsCreateAction = create => InternalCommsProjectsAccountManager.Database.AddContact(sourceContact);
        return CreateContact(internalCommsProjectsCreateAction, sourceContact);
    }

    private HttpStatusCode CreateEaAccountContact(ContactModel sourceContact)
    {
        Action<ContactModel> eaAccountContactCreateAction = create => EaAccountManager.Database.AddContact(sourceContact);
        return CreateContact(eaAccountContactCreateAction, sourceContact);
    }

    private HttpStatusCode CreateHrAccountContact(ContactModel sourceContact)
    {
        Action<ContactModel> hrAccountContactCreateAction = create => HrAccountManager.Database.AddContact(sourceContact);
        return CreateContact(hrAccountContactCreateAction, sourceContact);
    }

    private HttpStatusCode CreateContact(Action<ContactModel> dbUCreateAction, ContactModel sourceContact)
    {
        try
        {
            dbUCreateAction(sourceContact);
            return HttpStatusCode.Accepted;
        }
        catch (Exception e)
        {
            Log.Exception(e);
            return HttpStatusCode.InternalServerError;
        }
    }

    private ContactModel GetSourceModel(HttpRequestMessage request)
    {
        Log.Information("Webhooks - Message recieved");
        var body = request.Content.ReadAsStringAsync().Result;
        Log.Information(new LogCategory("Contact to process: "), body);

        var bodyDeserialised = new JavaScriptSerializer().Deserialize<BodyDeserialised>(body);
        var contact = new ContactModel();
        foreach (var datum in bodyDeserialised.Data)
        {
            var propertyInfo = contact.GetType().GetProperty(datum.Name.Replace(" ", string.Empty));

            if (propertyInfo != null)
                propertyInfo.SetValue(contact, datum.Value, null);
        }

        return contact;
    }

GeneralAccountManager.cs,HrAccountManager.cs etc etc, they all have same set of properties and method, just the naming is different.

using System;
using ClientProject.Common.Api;
using u2ool.Settings;

namespace WebhookApiUpdater.Infrastructure
{
    public enum GeneralAccountField
    {
        City,
        CompanyDescription,
        Country,
        CreateDate,
        Department,
        EmailAddress,
        EmployeeID,
        FunctionalDivision,
        Gender,
        GNADate,
        GNA,
        GroupDivision,
        HasMailbox,
        HireDate,
        ID,
        IsManager,
        IsSLT,
        LastModified,
        LastName,
        OCSAddress,
        OptOutDate,
        OptedOut,
        Optedback,
        OrganisationalRelationship,
        PersonID,
        PersonStatus,
        PreferredName,
        ReferenceID,
        Source,
        Version,
        JobProfile
    }


    [AttributeUsage(AttributeTargets.Property)]
    public class GeneralAccountFieldAttribute : Attribute, IMappableAttribute<GeneralAccountField>
    {
        public GeneralAccountField Field { get; }

        /// <summary>
        /// When using the FormMapping.AddFormParameters method, set to false to skip binding this property.
        /// </summary>
        public bool AutoBind { get; } = true;

        /// <param name="field">Specify a DatabaseField that this property is bound to</param>
        public GeneralAccountFieldAttribute(GeneralAccountField field)
        {
            Field = field;
        }
    }

    public class GeneralAccountManager : Manager<GeneralAccountField, GeneralAccountFieldAttribute> { }

    public class GeneralAccountMapping : Mapping<GeneralAccountField, GeneralAccountFieldAttribute> { }

    public class GeneralAccountFilter : Filter<GeneralAccountField> { }

    public class GeneralAccountSettings : EngageSettings<GeneralAccountField>
    {
        public GeneralAccountSettings(ISettingsContainer container, string prefix = null) : base(container, prefix)
        {
        }
    }
}
Dev
  • 171
  • 2
  • 18
  • are you after [Generics](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/)? – timur Feb 28 '20 at 00:11
  • Yes, Ideally... – Dev Feb 28 '20 at 00:17
  • does [this SO answer](https://stackoverflow.com/questions/3606595/understanding-c-sharp-generics-much-better/3606655) help you then? – timur Feb 28 '20 at 00:18
  • Sorry this might not be related to this as I'm not very sure how can i pass class as a parameter with base class inheritance and cast it back – Dev Feb 28 '20 at 00:23
  • right. I'm a bit unsure as to what the code you posted is meant to achieve - would you mind posting a minimal reproducible snippet somehow outlining the issue you're trying to solve? – timur Feb 28 '20 at 00:31
  • My Apology, I just added more detail. I would like to create a method that can be called by passing class object as a parameter like the following. all the classes have same properties just its mapping to different fields when its loaded. ProcessContact(sourceContact, GeneralAccountManager, GeneralAccountField, GeneralAccountFieldAttribute), ProcessContact(sourceContact, PaAccountManager,PaAccountField,PaAccountFieldAttribute), ProcessContact(sourceContact,HrAccountManager,HrAccountField,HrAccountFieldAttribute), – Dev Feb 28 '20 at 02:36

0 Answers0