Resolved Factory class in c#

Tanvi

Member
Joined
Feb 24, 2022
Messages
10
Programming Experience
1-3
Hi Team,
I am new to C#, I got a C#.Net Library for an API, that needs to be compatible with VBA. The API source code has a base class with parameterized constructors and Methods. How do I wrap or access the objects from VBA? Below is the sample code. I need to create objects for smartapi and pass arguments from VBA. I came to know that we can achieve this using Factory class. Can you guide me on how we can do it with some basic example on below SMartAPi base class?


C#:
public class SmartApi : ISmartApi
{
    protected string USER = "USER", SourceID = "WEB", PrivateKey = "";
    static string ClientPublicIP = "", ClientLocalIP = "", MACAddress = "";

    //protected string APIURL = "https://openapisuat.angelbroking.com";
    protected string APIURL = "https://apiconnect.angelbroking.com"; //prod endpoint

    AngelToken Token { get; set; }

    /*Constructors*/
    public SmartApi(string _PrivateKey)
    {
        PrivateKey = _PrivateKey;

        ClientPublicIP = Helpers.GetPublicIPAddress();
        if (ClientPublicIP == "")
            ClientPublicIP = Helpers.GetPublicIPAddress();

        if (ClientPublicIP == "")
            ClientPublicIP = "106.193.147.98";

        ClientLocalIP = Helpers.GetLocalIPAddress();

        if (ClientLocalIP == "")
            ClientLocalIP = "127.0.0.1";

        if (Helpers.GetMacAddress() != null)
            MACAddress = Helpers.GetMacAddress().ToString();
        else
            MACAddress = "fe80::216e:6507:4b90:3719";
    }
    
    public SmartApi(string _PrivateKey, string _jwtToken = "", string _refreshToken = "")
    {
        PrivateKey = _PrivateKey;

        this.Token = new AngelToken();
        this.Token.jwtToken = _jwtToken;
        this.Token.refreshToken = _refreshToken;
        this.Token.feedToken = "";

        ClientPublicIP = Helpers.GetPublicIPAddress();
        if (ClientPublicIP == "")
            ClientPublicIP = Helpers.GetPublicIPAddress();

        if (ClientPublicIP == "")
            ClientPublicIP = "106.193.147.98";

        ClientLocalIP = Helpers.GetLocalIPAddress();

        if (ClientLocalIP == "")
            ClientLocalIP = "127.0.0.1";

        if (Helpers.GetMacAddress() != null)
            MACAddress = Helpers.GetMacAddress().ToString();
        else
            MACAddress = "fe80::216e:6507:4b90:3719";
    }
    //other methods below
}
 
Solution
Instead of:
C#:
string Client_code = "“; //YOUR CLIENT CODE
string Password = ""; //YOUR PASSWORD
string api_key = "";
string JWTToken = "“; // optional
string RefreshToken = ""; // optional

SmartApi connect = new SmartApi(api_key, JWTToken, RefreshToken);

You would do:
C#:
string Client_code = "“; //YOUR CLIENT CODE
string Password = ""; //YOUR PASSWORD
string api_key = "";
string JWTToken = "“; // optional
string RefreshToken = ""; // optional

SmartApi connect = new SmartApi();
connect.ApiKey = api_key;
connect.JwtToken = JWTToken;
connect.RefreshToket = RefreshToken;
Was it your post in StackOverflow that lead you to believe that you needed a factory class?

 
Was it your post in StackOverflow that lead you to believe that you needed a factory class?


Yes, I've been following up, but not getting enough guidance from last 2 questions. I am basically DBA, got little knowledge in programming, but slowly connecting the dots. So did my research on how to make .net library visible to com like vba.
So the c# class has parameterized constructor in base class that will initiaze the connection (smartapi), which we i need to access from vba
 
So the constructor for that class needs some parameters. Will those be fixed forever? Or does the VBA code need to be able to set some of those values?

Anyway, unless your code above runs using side effects, I am not seeing anything there that demands that those values being passed in the constructor, be set as properties instead. (Read about constructor dependency injection vs. property dependency injection.) Why not just have a constructor that takes no parameters, then just set the private key, and tokens after instantiation.
 
So the constructor for that class needs some parameters. Will those be fixed forever? Or does the VBA code need to be able to set some of those values?

Anyway, unless your code above runs using side effects, I am not seeing anything there that demands that those values being passed in the constructor, be set as properties instead. (Read about constructor dependency injection vs. property dependency injection.) Why not just have a constructor that takes no parameters, then just set the private key, and tokens after instantiation.
Ok, so in that case we can avoid parameter constructor, could you just give sample code layout here from smartapi, and i will try to proceed further on skipping of parameter constructor
Badically smartapi class establish the connectiom object via apikey
Then from tha con object we can access other methods like fetch price etc...
 
C#:
public class SmartApi : ISmartApi
{
#if RELEASE
    protected const string APIURL = "https://apiconnect.angelbroking.com";
#else
    protected const string APIURL = "https://openapisuat.angelbroking.com";
#endif
    static readonly string ClientPublicIP;
    static readonly string ClientLocalIP;
    static readonly string MACAddress;

    static SmartApi()
    {
        ClientPublicIP = Helpers.GetPublicIPAddress();
        if (ClientPublicIP == "")
            ClientPublicIP = Helpers.GetPublicIPAddress();

        if (ClientPublicIP == "")
            ClientPublicIP = "106.193.147.98";

        ClientLocalIP = Helpers.GetLocalIPAddress();
        if (ClientLocalIP == "")
            ClientLocalIP = "127.0.0.1";

        MACAddress = "fe80::216e:6507:4b90:3719";
        if (Helpers.GetMacAddress() != null)
            MACAddress = Helpers.GetMacAddress().ToString();
    }

    protected string USER = "USER";
    protected string SourceID = "WEB";

    AngelToken _token = null;

    AngelToken Token
    {
        get
        {
            if (_token == null)
            {
                _token = new AngelToken();
                _token.jwtToken = JwtToken;
                _token.refreshToken = RefreshToken;
                _token.feedToken = "";
            }
            return _token;
        }

        set
        {
            if (value != _token)
                _token = value;
        }
    }

    public string PrivateKey { get; set; }
    public string JwtToken { get; set; }
    public string RefreshToken { get; set; }

    public SmartApi()
        : this("")
    {
    }

    public SmartApi(string privateKey, string jwtToken = "", string refreshToken = "")
    {
        PrivateKey = privateKey;
        JwtToken = jwtToken;
        RefreshToken = refreshToken;
    }
    //other methods below
}

Actually all you asked for is basically a constructor with no parameters. That's lines 60-63. Line 61 calls the other constructor with parameters (lines 65-70) pass in an empty string as the privateKey.

The constructor on lines 65-70 just copies the parameters passed in into the properties declared on lines 56-58.

The getter of the Token property (lines 37-47) does what is called "lazy initialization". If it sees that _token (from line 33) has not yet been set, it instantiates a brand new AngelToken and uses the JwtToken and RefreshToken property values.

I couldn't help myself. i just had to refactor your static strings and have them initialized by a type constructor on lines 12-28 because I couldn't see a normal case when a machines IP address and MAC addresses would change dynamically. If you do need to deal with this possibility, then move lines 14-27 into the constructor on lines 37-47.
 
@Skydriver, thanks a alot for guiding me in the correct direction. I just implemented your code. But from VBA I can able to view the private key as the smartapi property. just want to know how we initialize the connection from VBA. for the reference below is the source code in C#.
 
Instead of:
C#:
string Client_code = "“; //YOUR CLIENT CODE
string Password = ""; //YOUR PASSWORD
string api_key = "";
string JWTToken = "“; // optional
string RefreshToken = ""; // optional

SmartApi connect = new SmartApi(api_key, JWTToken, RefreshToken);

You would do:
C#:
string Client_code = "“; //YOUR CLIENT CODE
string Password = ""; //YOUR PASSWORD
string api_key = "";
string JWTToken = "“; // optional
string RefreshToken = ""; // optional

SmartApi connect = new SmartApi();
connect.ApiKey = api_key;
connect.JwtToken = JWTToken;
connect.RefreshToket = RefreshToken;
 
Solution
Instead of:
C#:
string Client_code = "“; //YOUR CLIENT CODE
string Password = ""; //YOUR PASSWORD
string api_key = "";
string JWTToken = "“; // optional
string RefreshToken = ""; // optional

SmartApi connect = new SmartApi(api_key, JWTToken, RefreshToken);

You would do:
C#:
string Client_code = "“; //YOUR CLIENT CODE
string Password = ""; //YOUR PASSWORD
string api_key = "";
string JWTToken = "“; // optional
string RefreshToken = ""; // optional

SmartApi connect = new SmartApi();
connect.ApiKey = api_key;
connect.JwtToken = JWTToken;
connect.RefreshToket = RefreshToken;
Yes, I am able to pass the parameter now from excel vba6, but just a small query, will it make any difference as the original code is taking 3 parameters (api_key, JWTToken, RefreshToken) at a time making JWTToken and RefreshToken opitional, so can we pass like the same.. something like connect.con = apikey, JWTToken, Refreshtoken
 
will it make any difference as the original code is taking 3 parameters (api_key, JWTToken, RefreshToken) at a time
As I previously said, as long as the code is not dependent on side effects, it shouldn't make a difference where all the parameters are parsed in at once, or if they are passed in one at a time. As long as the code that makes use of those parameters is invoked after the parameters are setup, things should work fine.
 
As I previously said, as long as the code is not dependent on side effects, it shouldn't make a difference where all the parameters are parsed in at once, or if they are passed in one at a time. As long as the code that makes use of those parameters is invoked after the parameters are setup, things should work fine.
So today I've done the testing, it worked flawlessly. Skydiver! you are the savior of a noob like me:), I've been following up in StackOverflow like a week for any leads but got not helpful replies..I am done with stackoverflow now.........God bless you always and forever....
 
Back
Top Bottom