Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Trying to get generic DataType class 1

Status
Not open for further replies.

tshad

Programmer
Jul 15, 2004
386
US
I have a DataType class I am setting to use in my Data class.

I want to be able to access each datatype without casting.

I was told this would work but I can't make it work.

Here is my class:

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestData
{
    public abstract class DataType
    {
		protected object _objInitial;
		protected object _objCurrent;
		private bool _fChanged;

        public bool IsNull
		{
			get { return _objCurrent == null; }
		}

		public bool IsFirstNull
		{
			get { return _objInitial == null; }
		}

		// Reset _objInitial to _objCurrent and changed flag to false to track
		// when this variable changes again.  This would be necessary if were to 
		// write out data to a database record and need to track when it changes again

		public void Reset()
		{
			_objInitial = _objCurrent;
			_fChanged = false;
		}

		public object First
		{
			get { return _objInitial; }
		}

		public object Data
		{
			get { return _objCurrent; }
			set
			{
				if (value == DBNull.Value) value = null;
				if (value != null) 
				{
					_ValidateType(value);
				}
				_objCurrent = value;
				_fChanged = true;
			}
		}

		// Likewise, I don't think Changed should include a setter
		public bool Changed
		{
			get { return _fChanged; }
		}

		// This is what deriving classes will define so the type can be checked
		abstract protected Type _TypeRequired { get; }

		private void _ValidateType(object obj)
		{
			Type typeRequired = _TypeRequired;

			// Depending on how you're using this class, you may instead prefer
			// to check for exact type equality.  The below simply 	requires that
			// the passed-in object has the required type in its inheritance chain.

			if(obj == DBNull.Value)
			{
				_fChanged = true;
			}
			if (!typeRequired.IsInstanceOfType(obj))
			{
				throw new ArgumentException("assigned value type of " +
					obj.GetType().Name + " is incompatible with  required type of " +
										typeRequired.Name);
			}
		}
	}       // End of DataType Class

	public class BoolType : DataType
	{
		public BoolType()
		{
		}

		public BoolType(bool initial)
		{
			_objInitial= initial;
			_objCurrent = initial;
		}

		// Each class defines this so that the base type can validate the data's type
		protected override Type _TypeRequired
		{
			get { return typeof(bool); }
		}

		// A convenience method so that no casting is needed when you already have
			// a fully typed object
			public bool TypedData
			{
				get { return (bool)Data; }
				set { Data = value; }
			}
	}

    public class StringType : DataType
    {
        public StringType()
        {
        }

        public StringType(string initial)
        {
            _objInitial = initial;
            _objCurrent = initial;
        }

        protected override Type _TypeRequired
        {
            get { return typeof(string); }
        }

        public string TypedData
        {
            get { return (string)Data; }
            set { Data = value; }
        }
    }
   
    public class IntType : DataType
    {
        public IntType()
        {
        }

        public IntType(int initial)
        {
            _objInitial = initial;
            _objCurrent = initial;
        }

        protected override Type _TypeRequired
        {
            get { return typeof(int); }
        }

        public int TypedData
        {
            get { return (int)Data; }
            set { Data = value; }
        }
    }
}

If I do the following:

Code:
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            StringType s1 = new StringType("Make it");
            IntType i1 = new IntType(15);
            string s2;
            int i2;

            s1.Data = "This is a test";
            s2 = s1.Data;    // This is an error saying I can't convert object to string
            i1.Data = 250;
            i2 = i1.Data;   // This is an error saying I can't convert object to int


        }

I was told that if I had this set of line in my code in each Datatype, I would not have to cast, but it doesn't seem to work.

Code:
		// A convenience method so that no casting is needed when you already have
			// a fully typed object
			public bool TypedData
			{
				get { return (bool)Data; }
				set { Data = value; }
			}

What am I missing?

Thanks,

Tom
 
You are using the Data field of the base class, where you should be using the TypedData field of the derived classes.

In other words:

Code:
s1.Data = "This is a test";
s2 = s1.TypedData;

This should work (unverified).

Regards, Ruffnekk
---
Is it true that cannibals don't eat clowns because they taste funny?
 
I see.

What I was trying to do was to objectify this as much as possible.

I could actually change TypedData to Data and inherit the class.

I would also need to do the same thing for First if I wanted it to return the value with having to cast it.

Would there be a way using a base class to set it up so I can set up each Type of field to use a base property to return the value without casting or would it have to be done as I have where I have to set up a property for each field type.

Thanks,

Tom
 
The following code will do what you want without casting at all. I have omitted all the "extra" code, just the necessary functionality.

Code:
    public abstract class DataType<T>
    {
        protected T _objCurrent;

        protected T _Data
        {
            get { return _objCurrent; }
            set { _objCurrent = value; }
        }
    }

    public class StringType : DataType<string>
    {
        public StringType(string initial)
        {
            _objCurrent = initial;
        }

        public string Data
        {
            get { return _Data; }
            set { _Data = value; }
        }
    }

I hope that helps you on your way.

John

Regards, Ruffnekk
---
Is it true that cannibals don't eat clowns because they taste funny?
 
Seems like a pretty good idea but I get an error with the classes:

'BusinessLayer.StringType' does not implement inherited abstract member 'BusinessLayer.DataType<string>._TypeRequired.get'

I get this for each type.

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BusinessLayer
{
    public abstract class DataType<T>
    {
		protected T _objInitial;
		protected T _objCurrent;
		private bool _fChanged;

        public bool IsNull
		{
			get { return _objCurrent == null; }
		}

		public bool IsFirstNull
		{
			get { return _objInitial == null; }
		}

		// Reset _objInitial to _objCurrent and changed flag to false to track
		// when this variable changes again.  This would be necessary if were to 
		// write out data to a database record and need to track when it changes again

		public void Reset()
		{
			_objInitial = _objCurrent;
			_fChanged = false;
		}

		public T _First
		{
			get { return _objInitial; }
		}

		public T _Data
		{
			get { return _objCurrent; }
			set
			{
                                    //if (value == DBNull.Value) value = null;
				if (value != null) 
				{
					_ValidateType(value);
				}
				_objCurrent = value;
				_fChanged = true;
			}
		}

		// Likewise, I don't think Changed should include a setter
		public bool Changed
		{
			get { return _fChanged; }
		}

		// This is what deriving classes will define so the type can be checked
		abstract protected Type _TypeRequired { get; }

		private void _ValidateType(object obj)
		{
			Type typeRequired = _TypeRequired;

			// Depending on how you're using this class, you may instead prefer
			// to check for exact type equality.  The below simply 	requires that
			// the passed-in object has the required type in its inheritance chain.

			if(obj == DBNull.Value)
			{
				_fChanged = true;
			}
			if (!typeRequired.IsInstanceOfType(obj))
			{
				throw new ArgumentException("assigned value type of " +
					obj.GetType().Name + " is incompatible with  required type of " +
										typeRequired.Name);
			}
		}
	}       // End of DataType Class

	public class BoolType : DataType<bool>
	{
		public BoolType()
		{
		}

		public BoolType(bool initial)
		{
			_objInitial= initial;
			_objCurrent = initial;
		}
	}

    public class StringType : DataType<string>
    {
        public StringType()
        {
        }

        public StringType(string initial)
        {
            _objInitial = initial;
            _objCurrent = initial;
        }
    }
   
    public class IntType : DataType<int>
    {
        public IntType()
        {
        }

        public IntType(int initial)
        {
            _objInitial = initial;
            _objCurrent = initial;
        }
    }
}

Thanks,

Tom
 
Nevermind the previous post.

I got it to work. It was a namespace problem.

I also put [Serializable] before each class (not the abstract class).

So your code would look something like:

Code:
    public abstract class DataType<T>
    {
        protected T _objCurrent;

        protected T _Data
        {
            get { return _objCurrent; }
            set { _objCurrent = value; }
        }
    }

    [Serializable]
    public class StringType : DataType<string>
    {
        public StringType(string initial)
        {
            _objCurrent = initial;
        }

        public string Data
        {
            get { return _Data; }
            set { _Data = value; }
        }
    }

    [Serializable]
    public class IntType : DataType<int>
    {
        public IntType(intinitial)
        {
            _objCurrent = initial;
        }

        public int Data
        {
            get { return _Data; }
            set { _Data = value; }
        }
    }

Is that right?

Thanks,

Tom
 
Yes that's correct. You can build on that base and expand the functionality.

Regards, Ruffnekk
---
Is it true that cannibals don't eat clowns because they taste funny?
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top