This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
Is there a way to specify that every Entity and Property should get Custom Attributes that are exposed via the model designer and then the object model. Basically I would like to use the LSModel designer as an entity modeling tool and have all entites get a common set of attributes and all properties a common set of attributes. I need to allow developers to change these in the model and then get to them in the codegen to control generation scenarios. What would also work is the ability to specificy the Entity and Property base classes used in the model designer and file. They could inherit from Entity your base class but add addiotnal properties. Right now, I can add custom properties but they have to be added to each entity manually.
|
|
|
This isn't currently supported. It might be possible to do something of this nature using Visual Studio extender providers but I think it would be a hard road (even if you could get your custom options displayed in the designer Properties box, I am not sure how you would get them saved in the .lsmodel file). Could you give us some representative examples of the kind of additional metadata you'd like to place against entities and properties, and the kind of workflow you'd envisage e.g. would you be specifying the additional metadata at the model level, project level or machine level? This would give us a better idea of what we might need to do to support this kind of scenario. |
|
|
There are a bunch of other things we would like to generate like UI shells. Also, we would like to control things like more sophisticated caching and mapping info for legacy systems. Ideally, we could control this at the model level. A solution might look like this: When creating a model you can provide a ICustomDecorator interface. This interface provides: ICustomModelDecorator, ICustomEntityDecorator, ICustomPropertyDecorator When designing a model, the model designer would expose these interfaces into a property editor so that properties on them could be edited. When saving a model the contents inside these objects get serialized to the xml file. Finally, duirng both codegen and runtime you can get access to these attributes. Let me know if any of this makes sense.
|
|
|
It makes sense, but I'd like to get a better handle on is the type and complexity of data you want to put into these extension properties. E.g. are we talking primitive things like ints, bools and strings, or do you need the ability to put Types or your own enums in there, or rich objects like custom classes or structs? I think we could probably do primitives (though I still need to look at serialisation issues), but more complicated stuff could be tricky. What level of control do you need over the editing experience, e.g. specifying custom editors in the property grid? Also, what are your expectations in terms of how much of this we handle in the standard templates? My assumption is that we will make the custom metadata available for use by custom templates, but that the default templates will ignore it (because we don't know whether to turn it into attributes, interfaces, methods, or whatever). Is that consistent with your expectation? |
|
|
I think initially exposing the fileds on ICustomXXXDecorator as simple types and Enums would be good enough. At some point full-fledged objects would be nice but it is not critical.
As far as code-gen, the template author can control this. I am not sure there is anything you need to do here. The key is that this data can be accessed at codegen time and runtime.
|
|
|
Okay, thanks. I'll have a look at this though I can't promise anything. One note of caution: we can't provide direct access to the metadata in the model at runtime. The designer model is purely a design-time artefact: it has no runtime existence; the only thing that exists at runtime is the compiled generated code. Any info that you need at runtime will therefore have to be emitted into the generated code, e.g. as an attribute or a constant. (This should be trivial for the template author to do, I just mention it to be clear that it won't happen automatically.) |
|
|
I noticed the the classes to manipulate the model are really second class citizens. They are not even documented. An interetsing approach would be to provide access to the Model as part of the DataContext. Then if there is custom data in the model, programmers can get to it Of course, we can always have a light-weight wrapper that loads the model and the DataContext. We would most likely do this anyways since there are a bunch of things we need to control besides this. The key things needed are:
|
|
|
That's correct: the classes that manipulate the model are internal to the designer. They are not part of the LightSpeed runtime or API. We are considering opening up the runtime model, probably after 3.0, but this is derived from the generated code; as part of this exercise it would makes sense to look into documenting the design-time metamodel and making that model available at runtime, but I think significant refactoring and tidying would be required to stabilise the API and make it easy to use. Also, at present there are limits to what we can do in terms of extensibility without major effort -- for example, you suggested using a custom design-time class to represent entities instead of the current Entity model class, but this would be very hard to do within the toolkit we currently use to build the designer. I have prototyped a simplified form of design-time extensibility which will basically allow you to add your own properties to metaobjects, edit them in the designer, and access them during code generation. I think this will answer your four must-have points albeit in a fairly simplistic way. I'm hoping to get this into the nightlies soon and we can then iterate from there. |
|
|
Let me know when you have something ready. I will take a look.
Thanks for your help.
|
|
|
Righty ho, experimental support for this stuff will be coming in the 20 May nightly, available from about 1430 GMT. Here's how to use it. Suppose you want to associate a display name with each entity and property, e.g. for use in UI generation. 1. Open or switch to the LightSpeed Model window (the tree view). 2. Right click the root node and choose Add Extension Property Definition. 3. Fill out the details in the Properties window e.g. Name = DisplayName, DataTypeName = System.String, Category = UI Generation, Extends = Entity | Property. Notes: DataTypeName must be the CLR name, including the namespace qualifier. C#/VB aliases are not supported. You must also specify the assembly unless the type is in mscorlib or System.dll (but see below). Category is optional. 4. You can now select an entity or property and the Properties window will show a DisplayName property for it. You can edit this value normally. Notes: The editor will be appropriate to the declared data type, e.g. a boolean or enum will get a drop-down. 5. Now open your custom template. * To get the value of the DisplayName property, use the expression $obj.GetExtendedPropertyValue("DisplayName") [e.g. $entity.GetExtendedPropertyValue("DisplayName"), etc.]. Notes: (a) This will NOT make the value into a literal: it just returns the value, an object of the data type you specified in step 3. For example if DisplayName is "My Object" and you write form.Text = $entity.GetExtendedPropertyValue("DisplayName"); then the generated code will be form.Text = My Object; and syntax error joy will follow. (b) This throws an exception if the extension property is not defined on the object. (See below.) * To get a language-specific literal for a value, call $Translator.TranslatePrimitive, e.g. form.Text = $Translator.TranslatePrimitive($entity.GetExtendedPropertyValue("DisplayName")); will generate form.Text = "My Object";. This will handle primitive types include booleans, enums, etc. * To determine if an extension property is defined on a particular instance, call HasExtendedProperty(propertyName). * To get the value of an extension property, defaulting it if the property is not defined on an instance, pass a default in as the second argument e.g. $entity.GetExtendedPropertyValue("DisplayName", $entity.Name). What about types defined in non-system assemblies, e.g. custom enums? To get at these, add a Design Time Assembly to the model and enter the path to the custom assembly. Please note that we only support compiled assemblies for this. You can then enter types from that assembly as if they were in System or mscorlib, i.e. namespace-qualified but not assembly-qualified. Finally I need to stress again that this is experimental support. There will undoubtedly be rough spots and errors, particularly if you start pushing the envelope with custom types, and ways in which it could be improved. We welcome your feedback and will be happy to iterate this with you -- though I should also confess that this is a fairly marginal, experts-only kind of feature so we do not want to spend too much effort on fit and finish at this stage. Please let us know about any problems or if you need any more information. |
|