Thrown together quickly for getting this challenge started, and has not been tested much.
Need to refactor it since it uses too much coupling and couple other things could be improved, but maybe good enough to get started
Attached the project which may be easier to understand.
Your class needs to implement the IXrecordProperties interface
public interface IXrecordProperties
{
string DictionaryName { get; }
List<string> PropertyNames { get; }
}
The DictionaryName is the name of the Dictionary that will be created and PropertyNames is a list of strings which are the properties that you want to save to a DBDictionary.
Here would be an example
public class TestClass : IXrecordProperties
{
const string DICT_NAME = "Dictionary_Test";
public string word { get; set; }
public int integer { get; set; }
public ObjectId id { get; set; }
public List<string> properties = new List<string>() { "word", "integer", "id" };
public TestClass()
{
}
public TestClass(string s, int i)
{
word = s;
integer = i;
}
public string DictionaryName
{
get { return DICT_NAME; }
}
public List<string> PropertyNames
{
get { return properties; }
}
}
You use this instead of a DBDictionary which inherits from a DBDictionary
public class XrecordDictionary : DBDictionary
{
public IXrecordProperties XrecordProperties { get; set; }
public XrecordDictionary (IXrecordProperties xrecordProperties)
{
XrecordProperties = xrecordProperties;
}
public void AddToNOD(Database db)
{
Transaction trx = db.TransactionManager.TopTransaction;
DBDictionary nod = (DBDictionary)trx.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForWrite);
nod.SetAt(XrecordProperties.DictionaryName, this);
trx.AddNewlyCreatedDBObject(this, true);
XrecordFactory.CreateTypedValuesFromProperties(XrecordProperties, this);
}
public void AddToDbObject(Database db, DBObject dbObject)
{
if (!dbObject.IsTransactionResident)
{
Application.ShowAlertDialog("Please put in a TransAction");
}
if (!dbObject.IsPersistent)
{
Application.ShowAlertDialog("Please add to the Database");
}
Transaction trx = db.TransactionManager.TopTransaction;
ObjectId extDictionaryId;
extDictionaryId = dbObject.ExtensionDictionary;
if (extDictionaryId == ObjectId.Null)
{
if (!dbObject.IsWriteEnabled)
{
dbObject.UpgradeOpen();
}
dbObject.CreateExtensionDictionary();
extDictionaryId = dbObject.ExtensionDictionary;
}
DBDictionary extDictionary = (DBDictionary)trx.GetObject(extDictionaryId, OpenMode.ForWrite);
extDictionary.SetAt(XrecordProperties.DictionaryName, this);
trx.AddNewlyCreatedDBObject(this, true);
XrecordFactory.CreateTypedValuesFromProperties(XrecordProperties, this);
}
public IXrecordProperties GetFromNOD(Database db)
{
Transaction trx = db.TransactionManager.TopTransaction;
DBDictionary nod = (DBDictionary)trx.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
ObjectId dicId = nod.GetAt(this.XrecordProperties.DictionaryName);
DBDictionary dic = (DBDictionary)trx.GetObject(dicId, OpenMode.ForRead);
XrecordFactory.SetPropertiesFromTypedValues(dic, this.XrecordProperties);
return XrecordProperties;
}
public IXrecordProperties GetFromDbObject(Database db, DBObject dbObject)
{
if (!dbObject.IsTransactionResident)
{
Application.ShowAlertDialog("Please put in a TransAction");
}
if (!dbObject.IsPersistent)
{
Application.ShowAlertDialog("Please add to the Database");
}
Transaction trx = db.TransactionManager.TopTransaction;
ObjectId extDictionaryId;
extDictionaryId = dbObject.ExtensionDictionary;
if (extDictionaryId == ObjectId.Null)
{
Application.ShowAlertDialog("Extension Dictionary does not exist");
}
DBDictionary extDictionary = (DBDictionary)trx.GetObject(extDictionaryId, OpenMode.ForRead);
ObjectId dicId = extDictionary.GetAt(this.XrecordProperties.DictionaryName);
DBDictionary dic = (DBDictionary)trx.GetObject(dicId, OpenMode.ForRead);
XrecordFactory.SetPropertiesFromTypedValues(dic, this.XrecordProperties);
return XrecordProperties;
}
}
2 helper classes that aid the XrecordDictionary
For getting the TypedValueCodes
// A class for getting the TypedValue Code from the Type
public class TypedValueCodes
{
public const int NONE = 0;
public const int TEXT = 1;
public const int POINT3D = 10;
//public const int POINT2D = 11;
//public const int VECTOR3D = 12;
//public const int VECTOR2D = 13;
public const int DOUBLE = 40;
public const int SHORT = 60;
public const int INT = 90;
//public const int CONTROL_STRING = 102;
public const int INT64 = 160;
public const int BYTE = 280;
//public const int BINARY_CHUNK = 310;
public const int HANDLE = 320;
public const int OBJECT_ID_SOFT = 330;
//public const int OBJECT_ID_HARD = 340;
private static Dictionary<Type, int> typedValueCodesDictionary = new Dictionary<Type, int>(){
{typeof(string), TEXT},
{typeof(Point3d), POINT3D},
//{typeof(Point2d), POINT2D},
//{typeof(Vector3d), VECTOR3D},
//{typeof(Vector2d), VECTOR2D},
{typeof(double), DOUBLE},
{typeof(short), SHORT},
{typeof(int), INT},
{typeof(Int64), INT64},
{typeof(byte), BYTE},
{typeof(Handle), HANDLE},
{typeof(ObjectId), OBJECT_ID_SOFT}};
public static int GetTypedValueCode(Type typ)
{
int result;
if (typedValueCodesDictionary.TryGetValue(typ, out result))
{
return result;
}
return NONE;
}
}
Getting and setting the Properties
//Not a good Name for it since it does not follow the Factory or AbstractFactory Pattern.
public class XrecordFactory
{
public static void CreateTypedValuesFromProperties(IXrecordProperties xrecordProperties, DBDictionary dictionary)
{
Transaction trx = dictionary.Database.TransactionManager.TopTransaction;
foreach (string str in xrecordProperties.PropertyNames)
{
PropertyInfo pi = xrecordProperties.GetType().GetProperty(str);
if (!pi.CanRead)
{
continue;
}
if (pi.PropertyType.IsValueType)
{
object val = pi.GetValue(xrecordProperties, null);
int typedValueCode = TypedValueCodes.GetTypedValueCode(pi.PropertyType);
if (typedValueCode == TypedValueCodes.NONE)
{
continue;
}
Xrecord xr = new Xrecord();
ResultBuffer rb = new ResultBuffer(new TypedValue(typedValueCode, val));
xr.Data = rb;
dictionary.SetAt(pi.Name, xr);
trx.AddNewlyCreatedDBObject(xr, true);
}
else if (pi.PropertyType == typeof(string))
{
object val = pi.GetValue(xrecordProperties, null);
Xrecord xr = new Xrecord();
ResultBuffer rb = new ResultBuffer(new TypedValue(TypedValueCodes.TEXT, val));
xr.Data = rb;
dictionary.SetAt(pi.Name, xr);
trx.AddNewlyCreatedDBObject(xr, true);
}
}
}
public static void SetPropertiesFromTypedValues(DBDictionary dbDictionary, IXrecordProperties xrecordProperties)
{
Database db = HostApplicationServices.WorkingDatabase;
Transaction trx = db.TransactionManager.TopTransaction;
foreach (DBDictionaryEntry entry in dbDictionary)
{
PropertyInfo pi = xrecordProperties.GetType().GetProperty(entry.Key);
Xrecord xr = (Xrecord)trx.GetObject(entry.Value, OpenMode.ForRead);
object obj = xr.Data.AsArray()[0].Value;
pi.SetValue(xrecordProperties, obj, null);
}
}
}
Finally 2 Test Commands
[CommandMethod("TestCommand")]
public void TestCommand()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
using (Transaction trx = db.TransactionManager.StartTransaction())
{
TestClass tc = new TestClass("TestStringNod", 40);
tc.id = db.LayerTableId;
XrecordDictionary xd = new XrecordDictionary(tc);
xd.AddToNOD(db);
BlockTableRecord model = (BlockTableRecord)trx.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite);
Line lne = new Line(Point3d.Origin, new Point3d(100, 100, 0));
model.AppendEntity(lne);
trx.AddNewlyCreatedDBObject(lne, true);
TestClass tc1 = new TestClass("TestStringExtDict", 1);
tc1.id = lne.ObjectId;
XrecordDictionary xd1 = new XrecordDictionary(tc1);
xd1.AddToDbObject(db, lne);
trx.Commit();
}
}
[CommandMethod("TestCommandRead")]
public void TestCommandRead()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
using (Transaction trx = db.TransactionManager.StartTransaction())
{
TestClass tc = new TestClass();
XrecordDictionary xd = new XrecordDictionary(tc);
tc = (TestClass)xd.GetFromNOD(db);
ed.WriteMessage("\n{0} {1} {2}", tc.word, tc.integer.ToString(), tc.id.ToString());
ObjectId lineId = ed.GetEntity("\nSelect Line Created").ObjectId;
Line lne = (Line)trx.GetObject(lineId, OpenMode.ForRead);
TestClass tc1 = new TestClass();
XrecordDictionary xd1 = new XrecordDictionary(tc1);
xd1.GetFromDbObject(db, lne);
ed.WriteMessage("\n{0} {1} {2}", tc1.word, tc1.integer.ToString(), tc1.id.ToString());
trx.Commit();
}
}
}