Link to home
Start Free TrialLog in
Avatar of Ali Shah
Ali ShahFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Class Hierarchies

Hi there, I am trying to write a library to use within my applications. I realised that it would be better and would be lot easier to use the library if i divide the class in different modules instead of having all methods, enums, properties in one class. I just wanted to follow Microsoft's pattern e.g. System.Web.UI.WebControls.
I also was looking to write something like Core.SQL.DML and may be Core.SQL.Query below is my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;

namespace ASPNetSupportFunctions
{
     public class Core
    {
        const string LIBNAME = "Functions Library";
        public const string SQL_INSERT_FAIL = "ERROR: SQL INSERT FAILED.";
        public const string SQL_UPDATE_FAIL = "ERROR: SQL UPDATE FAILED.";

        // regular expression for email patterns 

         public const string REGEX_EMAIL_PATTERN = "\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";

        //sql db getdate()

        //static public const string SQL_GETDATE = "getDate()";

        // SQL Server database variable typess

        const string DBType_Int = "int";
        const string DBType_SmallInt = "smallint";
        const string DBType_Decimal = "decimal";
        const string DBType_VarChar = "varchar";
        const string DBType_Char = "char";
        const string DBType_DateTime = "datetime";

        static System.Random ObjRandom = new Random(Convert.ToInt32(System.DateTime.Now.Ticks % System.Int32.MaxValue));

        static public string exceptionMessage;

        #region "Enumerations"

       static public enum ArrayListCompareMode : byte
        {
            added = 0,
            removed = 1
        };

   static public enum ErrorCode : short
        {
            No_Error,
            Object_Reference_Null,
            String_Empty,
            Connection_Not_Opened,
            Different_Array_Lengths,
            Invalid_Content,
            UnExpected_Error,
            Email_Not_Valid,
            Email_No_Subject,
            Email_No_Message
        };

   static public void TestM() { }
        #endregion

        static public bool blnQueryError;
        static public bool blnListControlLock = true; //' addition on deletion of new items forbidden!

        static public int GetRandomNumber(int low = 1, int high = 100)
        {
            // return the number between the optional low and high intgers

            return ObjRandom.Next(low, high + 0);

        }

        static public bool IsDate(string inputDate)
        {
            DateTime dt;
            return DateTime.TryParse(inputDate, out dt);
        }


         public class SQL
        {
              static public string SQL_GETDATE = "getDate()";
             
             static public void GetDate()
             {                  
             }

             static public class DML
             {
                 static public string whatever = "xxx";
             }
             static public class Query
             {
             }
        }


    }
}

Open in new window


The problem is that when i reference my library in another project i can see Core.SQL.DML (or any sub-classes) but i can't see the variable or public method defined in SQL class e.g Core.SQL.GetDate() is not accessible outside the class. I thought it should have been straight forward but stuck from yesterday.

kind regards
Avatar of kaufmed
kaufmed
Flag of United States of America image

Why are you using nested types for organizational structure rather than namespaces?
Avatar of Ali Shah

ASKER

Thanks for your comment, actually i have no idea how to do this. I have just started digging into .Net. If you don't mind would you guide me on how to start this?

regards
You're mixing here a lot of concepts.

First of all you should watch this video: How To Design A Good API and Why it Matters from Joshua Bloch.

Now for your code:
* Your mixing namespaces and nested classes. Core is normally a namespace, not a class.
* Use at least one file per published type, either class or enum.
* Don't use public const values. In most cases they are part of a class and should be published as a property. Especially when these values are not really a constant or may change due to requirements. E.g. your REGEX_EMAIL_PATTERN is not a global correct regex expression for an e-mail address. See Mail::RFC822::Address: regexp-based address validation for an almost correct one.
* Wrapping functions like IsDate() are dangerous. Especially when wrongly implemented. E.g.
namespace ConsoleApplication4
{
    using System;

    class Program
    {
        static void Main(string[] args)
        {
            string testValue= "";
            testValue = "1900-01-01";
            Console.WriteLine("{0}: {1}", testValue, IsDate(testValue));
            testValue = "01.01.1900";
            Console.WriteLine("{0}: {1}", testValue, IsDate(testValue));
            testValue = "31.12.1900";
            Console.WriteLine("{0}: {1}", testValue, IsDate(testValue));
            testValue = "00:00:01";
            Console.WriteLine("{0}: {1}", testValue, IsDate(testValue));
            Console.ReadKey();
        }
        
        static public bool IsDate(string inputDate)
        {
            DateTime dt;
            return DateTime.TryParse(inputDate, out dt);
        }
    }
}

Open in new window

The last value is clearly not a date.
You do not understand correctly what they do in System.Web.UI.WebControls. Web, UI and WebControls are not classes, they are imbricated namespaces. Think of the whole as subdirectories inside of a root System directory, and the whole as a path to your classes.

If I understand what you are trying to do, you should drop the Core and SQL classes, and make them part of the namespace, by defining the namespace the following way:

namespace ASPNetSupportFunctions.Core
{
        const string LIBNAME = "Functions Library";
        public const string SQL_INSERT_FAIL = "ERROR: SQL INSERT FAILED.";
        public const string SQL_UPDATE_FAIL = "ERROR: SQL UPDATE FAILED.";

        // ..... All your constants, no methods in the namespace itself
             
             public Class SQL
             {  
                 static public string SQL_GETDATE = "getDate()";
             
                 static public void GetDate()
                 {                  
                 }
             }

             static public class DML
             {
                 static public string whatever = "xxx";
             }
             static public class Query
             {
             }
}

Open in new window

Hi JamesBurger,

thanks for your reply as per your suggestion when i try to create namesapce it gives the error message on every type e.g const, string, bool etc and says that A namespace can't directly contain members such as fields or methods.

Please help.
Sorry, I did not notice them.

A namespace is a container for classes, it cannot contain variables and methods that need to be in classes.

So, stuff such as
static System.Random ObjRandom = new Random(Convert.ToInt32(System.DateTime.Now.Ticks % System.Int32.MaxValue));

static public string exceptionMessage;

Open in new window

and
static public void TestM() { }

Open in new window

must be moved inside of your classes. It's up to you to decide in wich classes you include them.

You might want to make Core a class instead of a part of the namespace. But then, it should be at the same level as SQL and DML, not include them as you did in your original code.
Just an addendum to public const values: Also think about the usage. E.g. SQL_INSERT_FAIL is a resource.
@ste5an

You may want to clarify what you mean by "resource". I know what you are referring to, but shah36 may not.
Well I have just discovered that if i reference the library to web, windows or WPF application all the methods and variable in all classes including the nested are accessible but if i reference my library to another class library (which is my requirement) the methods and const of the classes are not accessible but only nested classes are accessible.  

This seems bizarre
Do you understand the difference between static and instance members?
Sorry if i am wrong here But the static members have only one copy in memory while the instance members will have multiple copies when they are referred to.

For example the constructor provides us the facility to instantiate a class and it will create a new object of that class type in memory and we can access the non-static properties and methods of the class by instantiating the class.

 however as the static members can't be accessed by an instance of class because they are not instantiated with the new object of that class type
Almost entirely correct. The only issue is your last paragraph. Static members *can* be access by instance members--not the other way around. This is because static members are deemed to be related to the class, but not to any particular instance. Since a static member is not related to any particular instance, it cannot see any instance members.

The programmatic implication is that when you want to refer to a static member, you have to use the class name, not the name of an instance variable, when you want to refer to the static member. My concern now with you not being able to see the various members is whether or not you are properly referencing each type of member. If you are trying to use static members, then you should be using the class name (e.g. ClassName.StaticMember()); if you are trying to use instance members, then you should working against an instance of the class (e.g.  (new ClassName()).InstanceMember())
Thanks for testing purposes i have created a class library supadupa, created the dll and referenced the dll in web application and another class library project.

Web Application screen shot

as you can see here that the fields and methods of the nested SQL class are visible in asp.net application

User generated image
Here only the nested classes of SQL Class are visible and other methods and fields are not

Class Library screen shot
User generated image
ASKER CERTIFIED SOLUTION
Avatar of Ali Shah
Ali Shah
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
As there is no difference between "static public" and "public static", it's not the answer. The C# language specification does not require an specific order of class modifiers.