예제 #1
0
 public FieldTempNull(Obj parent_arg, string field_arg)
 {
     // A FieldTempNull is a placeholder object which exists so that the operation
     // of setting a new field value without manually calling add_field() can be accomplished.
     //
     // This works by putting a FieldTempNull in someObj[someFieldName]
     // when the .get on that is called for a not-present key,
     // then _replacing_ the FieldTempNull with a newly-create IObjField
     // of one of the "real" types when the .set is called on the FieldTempNull.
     //
     // As such, it needs to know the parent Obj and the field name by which it is accessed, unlike other IObjField types.
     //
     // The surprising thing is, how well this scheme seemed to work upon the first proper trial.
     //
     // TODO: Figure out whether there is some problem with this eccentric-but-seemingly-functional scheme...
     // This seems to approximately match  the "lazy initialization" pattern, per http://en.wikipedia.org/wiki/Lazy_initialization
     // Is also seems partially similar to the "null object"         pattern, per http://en.wikipedia.org/wiki/Null_Object_pattern
     // It also seems somewhat like the        "state pattern"       pattern, per http://en.wikipedia.org/wiki/State_pattern
     //
     parent_obj = parent_arg;
     field_name = field_arg;
 }
예제 #2
0
 void warn_add_OBJ_field_mismatch_with_archetype_field(Obj obj, string field_name, FieldType obj_field_type)
 {
     warn_at();
     Form1.stdout.print("         Field type mismatch with Archetype '{1}', ignoring OBJ field '{0}',\n" +
                        "         obj_field_type '{2}' != arch_field_type '{3}'\n",
                         field_name, obj.archetype.tag, obj_field_type.ToString(), obj.archetype[field_name].type.ToString());
 }
예제 #3
0
        public void create_some_objs()
        {
            Archetype aa = new Archetype("first_test_archetype", 7);

            // W00t, it looks like the FieldTempNull approach got rid of the need for these manual add_field() calls
            //aa.add_field("int_field",          FieldType.INT);
            //aa.add_field("string_field",       FieldType.STRING);
            //aa.add_field("decimal_field",      FieldType.DECIMAL);
            //aa.add_field("list_int_field",     FieldType.LIST_INT);
            //aa.add_field("list_string_field",  FieldType.LIST_STRING);
            //aa.add_field("list_decimal_field", FieldType.LIST_DECIMAL);

            Obj obj1 = new Obj(aa, "first_test_obj", 0);

            stdout.print("--- Scalar field types: ---\n");
            int ii = obj1["int_field"].iv;
            obj1["int_field"].iv = 99;
            stdout.print("ii={0},  obj1[].iv={1}\n", ii, obj1["int_field"].iv);  // expect ii=0, obj1[].iv=99

            string ss = obj1["string_field"].sv;
            obj1["string_field"].sv = "def hij";
            stdout.print("ss='{0}', obj1[].sv='{1}'\n", ss, obj1["string_field"].sv);  // expect ss='', obj1[].sv="def hij"

            decimal dd = obj1["decimal_field"].dv;
            obj1["decimal_field"].dv = 123.456M;
            stdout.print("dd={0},  obj1[].dv={1}\n", dd, obj1["decimal_field"].dv);  // expect dd=0, obj1[].dv=123.456

            stdout.print("\n");

            //if (false) {
            //    // Debug output related to the inheritance-of-interface bug found in FieldID and FieldListID:
            //    FieldID argh = new FieldID();
            //    stdout.print("FieldID                               : GetType={0}, type={1}\n", argh.GetType(), argh.type);  // Returns FieldID and ID -- CORRECT

            //    IObjField xzzy = new FieldID();
            //    stdout.print("IObjField, manual cast upon use       : GetType={0}, type={1}\n", ((FieldID) xzzy).GetType(), ((FieldID) xzzy).type);  // Returns FieldID and ID -- CORRECT, have to manually cast upon use??? In the name of all that is static typing, WHY???

            //    IObjField horg = (FieldID) new FieldID();
            //    stdout.print("IObjField, manual cast upon assignment: GetType={0}, type={1}\n", horg.GetType(), horg.type);  // Returns FieldID and INT -- WRONG, why??? (cast did not make the difference)

            //    IObjField slar = new FieldID();
            //    stdout.print("IObjField, no cast                    : GetType={0}, type={1}\n", slar.GetType(), slar.type);  // Returns FieldID and INT -- WRONG, why???
            //    // (The why is due to "implementation of interfaces" not being inherited;
            //    // thus FieldID and FieldListID needed to explicitly indicate that they implement IObjField

            //    stdout.print("\n");
            //}

            aa.add_field("ID_field_1", FieldType.ID);

            //stdout.print("aa[ID_field_1].type   = {0}\n", aa["ID_field_1"].type);    // Prints ID
            //stdout.print("obj1[ID_field_1].type = {0}\n", obj1["ID_field_1"].type);  // Prints ID (but not if FieldID does not explicitly specify implmentation of IObjField)
            //stdout.print("\n");

            obj1["ID_field_1"].iv = 7;  // 7 is known valid ID
            int ID1 = obj1["ID_field_1"].iv;
            stdout.print("ID={0,3}, obj1[].iv={1}\n", ID1, obj1["ID_field_1"].iv);  // Expect ID=7, obj1[].iv=7
            stdout.print("\n");

            stdout.print("--- List field types: ---\n");

            obj1["list_int_field"    ].ilist = new List<int>     { 1, 2, 3 };
            obj1["list_int_field"    ].ilist.Add(42);
            obj1["list_string_field" ].slist = new List<string>  { "abc", "def", "hij" };
            obj1["list_string_field" ].slist.Add("xyz");
            obj1["list_decimal_field"].dlist = new List<decimal> { 1.1M, 2.2M, 3.3M };
            obj1["list_decimal_field"].dlist.Add(999.999M);
            stdout.print("list_int_field     = {0}\n", obj1["list_int_field"].ToString());
            stdout.print("list_string_field  = {0}\n", obj1["list_string_field" ].ToString() );
            stdout.print("list_decimal_field = {0}\n", obj1["list_decimal_field"].ToString() );
            stdout.print("\n");

            Archetype a1 = new Archetype("foo_arch", 100);
            Obj o1 = new Obj(a1, "foo_o1", 101);
            Archetype a2 = new Archetype("bar_arch", 200);
            Obj o2 = new Obj(a2, "bar_o2", 201);
            Obj o3 = new Obj(a2, "bar_o3", 202);
            Obj o4 = new Obj(a2, "bar_o4", 203);
            obj1["list_ID_field"].ilist = new List<int> { 100, 101, 200, 201 };
            obj1["list_ID_field"].ilist.Add(a1.ID);  // ID == 100, Dupe Archetype ID in list is valid
            obj1["list_ID_field"].ilist.Add(o3.ID);  // ID == 202
            obj1["list_ID_field"].ilist.Add(o1.ID);  // ID == 101, Dupe Obj ID in list is valid
            obj1["list_ID_field"].ilist.Add(o4.ID);  // ID == 203

            stdout.print("list_ID_field      = {0}\n", obj1["list_ID_field"].ToString() );  // Expect [100, 101, 200, 201, 100, 202, 101, 203]
        }
예제 #4
0
        public void create_some_objs()
        {
            Archetype aa = new Archetype("first_test_archetype", 7);

            // W00t, it looks like the FieldTempNull approach got rid of the need for these manual add_field() calls
            //aa.add_field("int_field",          FieldType.INT);
            //aa.add_field("string_field",       FieldType.STRING);
            //aa.add_field("decimal_field",      FieldType.DECIMAL);
            //aa.add_field("list_int_field",     FieldType.LIST_INT);
            //aa.add_field("list_string_field",  FieldType.LIST_STRING);
            //aa.add_field("list_decimal_field", FieldType.LIST_DECIMAL);

            Obj obj1 = new Obj(aa, "first_test_obj", 0);

            stdout.print("--- Scalar field types: ---\n");
            int ii = obj1["int_field"].iv;

            obj1["int_field"].iv = 99;
            stdout.print("ii={0},  obj1[].iv={1}\n", ii, obj1["int_field"].iv);  // expect ii=0, obj1[].iv=99

            string ss = obj1["string_field"].sv;

            obj1["string_field"].sv = "def hij";
            stdout.print("ss='{0}', obj1[].sv='{1}'\n", ss, obj1["string_field"].sv);  // expect ss='', obj1[].sv="def hij"

            decimal dd = obj1["decimal_field"].dv;

            obj1["decimal_field"].dv = 123.456M;
            stdout.print("dd={0},  obj1[].dv={1}\n", dd, obj1["decimal_field"].dv);  // expect dd=0, obj1[].dv=123.456

            stdout.print("\n");

            //if (false) {
            //    // Debug output related to the inheritance-of-interface bug found in FieldID and FieldListID:
            //    FieldID argh = new FieldID();
            //    stdout.print("FieldID                               : GetType={0}, type={1}\n", argh.GetType(), argh.type);  // Returns FieldID and ID -- CORRECT

            //    IObjField xzzy = new FieldID();
            //    stdout.print("IObjField, manual cast upon use       : GetType={0}, type={1}\n", ((FieldID) xzzy).GetType(), ((FieldID) xzzy).type);  // Returns FieldID and ID -- CORRECT, have to manually cast upon use??? In the name of all that is static typing, WHY???

            //    IObjField horg = (FieldID) new FieldID();
            //    stdout.print("IObjField, manual cast upon assignment: GetType={0}, type={1}\n", horg.GetType(), horg.type);  // Returns FieldID and INT -- WRONG, why??? (cast did not make the difference)

            //    IObjField slar = new FieldID();
            //    stdout.print("IObjField, no cast                    : GetType={0}, type={1}\n", slar.GetType(), slar.type);  // Returns FieldID and INT -- WRONG, why???
            //    // (The why is due to "implementation of interfaces" not being inherited;
            //    // thus FieldID and FieldListID needed to explicitly indicate that they implement IObjField

            //    stdout.print("\n");
            //}

            aa.add_field("ID_field_1", FieldType.ID);

            //stdout.print("aa[ID_field_1].type   = {0}\n", aa["ID_field_1"].type);    // Prints ID
            //stdout.print("obj1[ID_field_1].type = {0}\n", obj1["ID_field_1"].type);  // Prints ID (but not if FieldID does not explicitly specify implmentation of IObjField)
            //stdout.print("\n");

            obj1["ID_field_1"].iv = 7;  // 7 is known valid ID
            int ID1 = obj1["ID_field_1"].iv;

            stdout.print("ID={0,3}, obj1[].iv={1}\n", ID1, obj1["ID_field_1"].iv);  // Expect ID=7, obj1[].iv=7
            stdout.print("\n");

            stdout.print("--- List field types: ---\n");

            obj1["list_int_field"].ilist = new List <int>     {
                1, 2, 3
            };
            obj1["list_int_field"].ilist.Add(42);
            obj1["list_string_field"].slist = new List <string>  {
                "abc", "def", "hij"
            };
            obj1["list_string_field"].slist.Add("xyz");
            obj1["list_decimal_field"].dlist = new List <decimal> {
                1.1M, 2.2M, 3.3M
            };
            obj1["list_decimal_field"].dlist.Add(999.999M);
            stdout.print("list_int_field     = {0}\n", obj1["list_int_field"].ToString());
            stdout.print("list_string_field  = {0}\n", obj1["list_string_field"].ToString());
            stdout.print("list_decimal_field = {0}\n", obj1["list_decimal_field"].ToString());
            stdout.print("\n");

            Archetype a1 = new Archetype("foo_arch", 100);
            Obj       o1 = new Obj(a1, "foo_o1", 101);
            Archetype a2 = new Archetype("bar_arch", 200);
            Obj       o2 = new Obj(a2, "bar_o2", 201);
            Obj       o3 = new Obj(a2, "bar_o3", 202);
            Obj       o4 = new Obj(a2, "bar_o4", 203);

            obj1["list_ID_field"].ilist = new List <int> {
                100, 101, 200, 201
            };
            obj1["list_ID_field"].ilist.Add(a1.ID);                                       // ID == 100, Dupe Archetype ID in list is valid
            obj1["list_ID_field"].ilist.Add(o3.ID);                                       // ID == 202
            obj1["list_ID_field"].ilist.Add(o1.ID);                                       // ID == 101, Dupe Obj ID in list is valid
            obj1["list_ID_field"].ilist.Add(o4.ID);                                       // ID == 203

            stdout.print("list_ID_field      = {0}\n", obj1["list_ID_field"].ToString()); // Expect [100, 101, 200, 201, 100, 202, 101, 203]
        }
예제 #5
0
        public void test_set_invalid_ID_values_in_Obj()
        {
            stdout.print("--- ID field types (set invalid ID values): ---\n");
            Archetype bad_arch = new Archetype("arch_to_set_invalid_ID_fields", 0);
            bad_arch.add_field("invalid_ID", FieldType.ID);
            bad_arch.add_field("invalid_LIST_ID", FieldType.LIST_ID);

            Obj bad_obj = new Obj(bad_arch, "obj_to_get_invalid_ID_fields", 0);

            bad_obj["invalid_ID"].iv = 9999;  // Known invalid ID -- should fail (does fail, OK)
            stdout.print("bad_obj[invalid_ID] = {0}\n", bad_obj["invalid_ID"].ToString());

            bad_obj["invalid_LIST_ID"].ilist = new List<int> { 9999, 8888, 7777 };  // Known invalid IDs -- should fail (does fail, OK)
            stdout.print("bad_obj[invalid_LIST_ID] = {0}\n", bad_obj["invalid_LIST_ID"].ToString());

            // The add_field() method is available to control the type which would otherwise be auto-vivified:
            bad_obj.add_field("obj_added_ID_field", FieldType.ID);  // Without this, the field becomes an INT upon auto-vivify
            bad_obj["obj_added_ID_field"].iv = 999;  // 999 is known-invalid ID -- this fails because we called add_field() earlier
            int ID = bad_obj["obj_added_ID_field"].iv;
            stdout.print("bad_obj[obj_added_ID_field].type = {0}\n", bad_obj["obj_added_ID_field"].type);  // prints ID, would print INT if we had not done add_field() earlier
            stdout.print("ID={0,3}, bad_obj[].iv={1}\n", ID, bad_obj["obj_added_ID_field"].iv);  // Expect ID=999, obj1[].iv=999  (if we had gotten this far)
        }