0

I'm working on a framework capable of synchronizing CRM data bidirectionally between two restful services.

Among other things, I've defined a set of objects that have a common base class, and a couple of classes representing both services that also have a common base class.

I've defined some sparse interfaces for the object(s), and the service(s).

One problem I've been bumping into is how and where to store the information regarding the restful communications. For instance, to create or update a customer on one service, it must use a route of "/customer" and PUT. If I want to do it on the other, its "/individual" and POST. etc and so forth.

So far, I've created a reusable "RestConfig" class capable of holding this information.

Since this service specific API information is unlikely to change, I am going to store it in the objects, to be recalled when needed. It is easily done, however I really want to be strictly forced to add this class object for each instance of the inherited base SERVICE class that I create.

I'm doing this partly as an exercise in academia, to learn if this is possible. I already know how to do it by just adding public property of type RestConfig and manually hydrating it... But I digress.

My coworkers told me I should just define it all in the services, but my goal here is to create a very simple model where once its configured, you only need to use object.save(serviceEnvironment);

I'm honestly very close having a working example, but I really want to figure out if its possible do what I explained above.

Sorry if this is absurdly confusing. I expect to see some questions.. I'll make edits to clarify.

EDIT 1: Share code

Example of an object:

public class Customer : 
    EntityBase
    {

        public Customer() : base(new EntityBaseConfig("customer", Customer.RestFullConfig))
        {

        }

        [MagentoJsonDetails(PropertyName = "website_id", IsId = true, BasePath = JsonDetailsBase.JsonBasePath.Root, JsonValueType = typeof(int))]
        public int WebsiteId => 1;

        [MagentoJsonDetails(PropertyName = "store_id", IsId = true, BasePath = JsonDetailsBase.JsonBasePath.Root, JsonValueType = typeof(int))]
        public int StoreId => 1;

        [MagentoJsonDetails(PropertyName = "addresses", BasePath = JsonDetailsBase.JsonBasePath.Root, JsonValueType = typeof(List<Address.Address>))]
        public List<Address.Address> Addresses { get; set; }

        [MagentoJsonDetails(PropertyName = "group_id", IsId = true, BasePath = JsonDetailsBase.JsonBasePath.Root, JsonValueType = typeof(int))]
        [UseInHash(Position = 12)]
        public int GroupId { get; set; }

Example of a service:

public class MagentoSttiService : SttiServiceBase, ISttiService
{
    public SttiServiceEnvironment SttiServiceEnv { get; set; }

    public MagentoSttiService() : this(null)
    {

    }

    public MagentoSttiService(SttiServiceEnvironment env)
    {
        this.SttiServiceEnv = env;
    }

    public string SimpleGet(EntityBase entity, string json)
    {
        throw new NotImplementedException();
    }

    public string SimpleDelete(EntityBase entity, string json)
    {
        throw new NotImplementedException();
    }

    public string SimpleSave(EntityBase entity, string json)
    {
        Dictionary<SttiServiceBase.RestFullServiceConfig, string> restConfig = entity.EbConfig.RestFullConfig;

        string method = restConfig[SttiServiceBase.RestFullServiceConfig.Method];
        string url = restConfig[SttiServiceBase.RestFullServiceConfig.Url];

        if (entity.NKIId > 0)
        {
            method = WebRequestMethods.Http.Put;
            url += entity.NKIId.ToString();
        }

        return this.MakeCall(method, url, json);

    }

Example of how its used:

string json = "{\"id\":30,\"group_id\":98,\"default_billing\":\"2\",\"default_shipping\":\"2\",\"created_at\":\"2016-10-31 14:42:59\",\"updated_at\":\"2016-10-31 15:16:30\",\"created_in\":\"Default Store View\",\"dob\":\"1980-07-09\",\"email\":\"mitch@stti.org\",\"firstname\":\"Mitchell\",\"lastname\":\"Thompson\",\"middlename\":\"David\",\"prefix\":\"Mr\",\"suffix\":\"na\",\"gender\":1,\"store_id\":1,\"website_id\":1,\"addresses\":[{\"id\":2,\"customer_id\":30,\"region\":{\"region_code\":\"IN\",\"region\":\"Indiana\",\"region_id\":24},\"region_id\":24,\"country_id\":\"US\",\"street\":[\"550 West North Street\",\"IT Department\"],\"company\":\"Sigma Theta Tau Intlll\",\"telephone\":\"7655555555\",\"postcode\":\"46202\",\"city\":\"Indianapolis\",\"firstname\":\"Mitchell\",\"lastname\":\"Thompson\",\"middlename\":\"D\",\"default_shipping\":true,\"default_billing\":true,\"custom_attributes\":[{\"attribute_code\":\"cxa_key\",\"value\":\"5ecc8a60-8878-4c87-9734-26fc83dca15c\"}]}],\"disable_auto_group_change\":0,\"custom_attributes\":[{\"attribute_code\":\"stti_position\",\"value\":\"450,451,452\"},{\"attribute_code\":\"cst_key\",\"value\":\"3b4d43ba-bcc7-4255-9d25-d79f0035b7f6\"},{\"attribute_code\":\"constit_id\",\"value\":\"123456\"},{\"attribute_code\":\"cust_save_hash\",\"value\":\"thisIsATestHashThing\"},{\"attribute_code\":\"stti_specialty\",\"value\":\"413,414,415\"}]}";

            SttiServiceEnvironment sse = new SttiServiceEnvironment("http://192.168.5.65", "quwtldm4xa1a8bx1lncvwdlchuum1iee");

    // Newtonsoft parse the data into an object
    JObject data = JObject.Parse(json);

    // This just makes json into a Customer object 
    MagentoJsonConverter jConverter = new MagentoJsonConverter(typeof(MagentoJsonDetailsAttribute));

    Customer customerObjectData = jConverter.ConvertTo<Customer>(data);

    // Fricken save for Magento
    customerObjectData.Sync<MagentoSttiService>(jConverter, sse);

EDIT 2: Added this to my object's base class

public virtual void Sync<T>(IJsonConverter jConverter, SttiServiceEnvironment servEnv) where T : ISttiService, new()
    {
        // Pass arguments to T() that are defined in the interface
        ISttiService srv = new T() { SttiServiceEnv = servEnv };
        string json = jConverter.GetJson(this);
        srv.SimpleSave(this, json);
    }
CarComp
  • 1,929
  • 1
  • 21
  • 47
  • I think you missed a in your title. – Bradley Uffner Feb 01 '17 at 18:18
  • You really need to post some code for us to know what you're asking/doing – Jon Feb 01 '17 at 18:19
  • Dang. I was really hoping to get out of that. The code is really complicated. I'll try to pick apart enough to make an example. – CarComp Feb 01 '17 at 18:21
  • If I understand your question correctly, you can force a subclass to provide an implementation of a property / method by marking it `abstract` on the base class. – Bradley Uffner Feb 01 '17 at 18:24
  • Your title and description don't seem to be related. – Heretic Monkey Feb 01 '17 at 18:24
  • I'm bad with terminology – CarComp Feb 01 '17 at 18:25
  • If your classes are all derived from certain abstract classes, why wouldn't this simply be an abstract property of the base class? Or you are asking something else? – vgru Feb 01 '17 at 18:26
  • Now that I read your question a few more times, I think I understand what you are asking. If your class *requires* a property to by set, you should have it as a argument in the constructor. The constructor then populates the property backing for you. That way the class can't be instantiated without providing the value. – Bradley Uffner Feb 01 '17 at 18:26
  • I agree, however are there good ways to go about this using T instead of Activator.CreateInstance? – CarComp Feb 01 '17 at 18:28
  • 1
    Possibly related: http://stackoverflow.com/questions/619856/interface-defining-a-constructor-signature – Scott Mermelstein Feb 01 '17 at 18:28
  • If you are using generics and you want to be able to create a new instance of `T` from within the class, `T` needs to be constrained with `new`. That will allow you to do `SomeProperty = new T();`. see https://msdn.microsoft.com/en-us/library/sd2w2ew5.aspx . That limits you to a parameterless constructor though. If `T` requires arguments, I think instantiation through reflection is your only option. – Bradley Uffner Feb 01 '17 at 18:29
  • You've all given me some ideas to consider that I hadn't though of. – CarComp Feb 01 '17 at 18:37

0 Answers0