Book a Demo

Author Topic: Creating a read-only property  (Read 6614 times)

Michael McMullin

  • EA Novice
  • *
  • Posts: 6
  • Karma: +0/-0
    • View Profile
Creating a read-only property
« on: August 03, 2007, 12:30:48 pm »
Hi, this is my first post, very new to EA and UML, but love it so far!

I'm putting a class diagram together, and I've hit a wall. My target language is C#, and I'm creating a class that is derived from one of the existing System classes. I've imported the appropriate binary module, and created the derived class... so far so good.

One of the base class properties is protected, but I'd like to create a public read-only property in the derived class that returns its value. This is what I've tried so far:

Attempt #1: Created an attribute and checked the 'Property' box. Filled in the appropriate details. However, it creates a new attribute with the same name as the attribute in the base class, which obviously won't compile without manually removing it from the generated code.

Attempt #2: Instead of creating an attribute, I created an operation, and gave it a stereotype of 'property'. However, I can't figure out how to restrict it to read-only, and the resulting code looks like this:

Code: [Select]
public IList Regions{

get{


return <unknown>;

}

set{


<unknown> = value;

}
}


The <unknown> text should obviously be the value from the base class. I've probably overlooked something obvious from the manual, but if anyone can point me in the right direction, I'd really appreciate it!

«Midnight»

  • EA Guru
  • *****
  • Posts: 5651
  • Karma: +0/-0
  • That nice Mister Grey
    • View Profile
Re: Creating a read-only property
« Reply #1 on: August 03, 2007, 01:22:00 pm »
Welcome Michael,

Don't panic, you're almost there.

You had it right on Attempt #1, but were missing the 'magic' ingredient.

Open the Options dialog - use Tools | Options or control-F9, then choose the Source Code Engineering page. Do not go to the C# page for this, since you want to set a general option.

Near the bottom you will see the heading Remove prefixes when generating Get/Set properties. This is a semicolon-separated list. (AFAIK) Case is significant here, at least as far as C# is concerned. Make sure the prefix you use is in the list - or use one from the list later in this process if you want - and set the nearby check boxes as you prefer.

Now make sure your private attribute has an appropriate prefix, and repeat Attempt #1. You will notice that the proposed property name is now different (and derived from the attribute name). You can now uncheck the Write box, and the property will be created.

For example, in class Foo you can have a private attribute mFoobar. The dialog will create a public (or whatever you set) read-only property named Foobar.

Voila!

David

PS: The options on the above dialog are 'sticky' and will be the default in future EA sessions until you change them again.
No, you can't have it!

Michael McMullin

  • EA Novice
  • *
  • Posts: 6
  • Karma: +0/-0
    • View Profile
Re: Creating a read-only property
« Reply #2 on: August 03, 2007, 02:30:42 pm »
Hi David,

Thanks for the reply, your advice actually helped with another problem I was having!

In this case, however, I might be missing something. You see, the private attribute is part of an existing System class, so unfortunately, I have no control over how it is named.

Specifically, there is a class called MasterPage that contains a protected property called ContentPlaceHolders.

There is another class called Page that contains a property called Master (of type MasterPage). I need to be able to read the value of Master.ContentPlaceHolders, so I figured I'd create a class (say, MyMasterPage) which is derived from MasterPage, but contains a public property that returns the value of ContentPlaceHolders.

It's actually quite easy to code by hand:

Code: [Select]
public class MyMasterPage : MasterPage{
 public IList MyContentPlaceHolders{
   get { return ContentPlaceHolders; } // from base class
 }
}


I'm just not sure how to represent this in EA. The closest I get is something like:

Code: [Select]
public class MyMasterPage : MasterPage{
 protected IList ContentPlaceHolders; // ERROR -- ContentPlaceHolders already exists in MasterPage.

 public IList MyContentPlaceHolders{
   get { return ContentPlaceHolders; } // from base class
 }
}


Michael McMullin

  • EA Novice
  • *
  • Posts: 6
  • Karma: +0/-0
    • View Profile
Re: Creating a read-only property
« Reply #3 on: August 03, 2007, 02:58:58 pm »
As an update, I just tried something else:

First, I left out the public property and generated the C# code. The result was:

Code: [Select]
...
public class MyMasterPage : MasterPage {
 public MyMasterPage(){
 }

 ~MyMasterPage(){
 }
}//end MyMasterPage...


Next, I manually added the appropriate property to the code file:

Code: [Select]
...
public class MyMasterPage : MasterPage {
 public MyMasterPage(){
 }

 ~MyMasterPage(){
 }

 public IList MyContentPlaceHolders{
   get{
     return ContentPlaceHolders;
   }
 }
}//end MyMasterPage...


Then I went back to the model and synchronized it with the code. The property now appeared in the class diagram without the base protected property showing, which is what I'm looking for.

However, when I generate the code from this new model, EA seems to have changed it:

Code: [Select]
...
public class MyMasterPage : MasterPage {
 public MyMasterPage(){
 }

 ~MyMasterPage(){
 }

 public IList MyContentPlaceHolders{
   get{
     return <unknown>;
   }
 }
}//end MyMasterPage...


...That <unknown> text is back!

Michael McMullin

  • EA Novice
  • *
  • Posts: 6
  • Karma: +0/-0
    • View Profile
Re: Creating a read-only property
« Reply #4 on: August 03, 2007, 11:32:12 pm »
A-ha! When I synchronized the model with the code previously, I was deleting the source file afterwards and re-generating it. If I don't delete it, EA retains the manual changes.

Amazing how obvious things become after a good night's sleep...

Is this the most appropriate way of getting what I'm looking for? I can live with it, but I'd like to be sure it's good practice.

«Midnight»

  • EA Guru
  • *****
  • Posts: 5651
  • Karma: +0/-0
  • That nice Mister Grey
    • View Profile
Re: Creating a read-only property
« Reply #5 on: August 04, 2007, 05:03:48 am »
Hi Michael,

That's  progress, but somehow it seems like far too much work to get the desired result.

I need to study this a bit, but I still think this can be made to work the first time through.

David
No, you can't have it!

«Midnight»

  • EA Guru
  • *****
  • Posts: 5651
  • Karma: +0/-0
  • That nice Mister Grey
    • View Profile
Re: Creating a read-only property
« Reply #6 on: August 04, 2007, 05:09:20 am »
Michael,

Code: [Select]
public class MyMasterPage : MasterPage{
 protected IList ContentPlaceHolders; // ERROR -- ContentPlaceHolders already exists in MasterPage.

 public IList MyContentPlaceHolders{
   get { return ContentPlaceHolders; } // from base class
 }
}

I think you've done it the wrong way around. Assuming that the prefix "My" is in the list I mentioned above, you want the attribute to have the prefix. Thus, you want to declare:

protected IList MyContentPlaceHolders;

When you set the attribute in EA, it will strip the prefix, and generate (assuming you clear the Read box):

public IList ContentPlaceHolders{
   get { return MyContentPlaceHolders; }
}

David
No, you can't have it!

Michael McMullin

  • EA Novice
  • *
  • Posts: 6
  • Karma: +0/-0
    • View Profile
Re: Creating a read-only property
« Reply #7 on: August 05, 2007, 02:02:13 am »
Hi David,

Yes, it does seem like a clumsy way of getting the desired result! ;D

Unfortunately, in this case, I cannot rename the attribute as it already exists in the base class. So, I'm trying to create a property in EA that returns the value of an attribute in the base class, without re-creating the original attribute in the derived class. I've called the property MyContentPlaceHolders for now, but the name can be anything other than ContentPlaceHolders really, otherwise it will conflict with the base attribute name.

I've come up with another way, see what you think. I've created an operation called MyContentPlaceHolders, and set the stereotype to property. In the Behavior tab, I added the initial code:

get { return ContentPlaceHolders; }

That seems to generate the correct code that I need.

Thanks a million for your input on this one so far, I really appreciate it!

«Midnight»

  • EA Guru
  • *****
  • Posts: 5651
  • Karma: +0/-0
  • That nice Mister Grey
    • View Profile
Re: Creating a read-only property
« Reply #8 on: August 05, 2007, 02:19:56 am »
Good stuff Michael,

BTW, if you were not trying to generate your subclass, but were coding it by hand, how would you go about naming things? It strikes me that this might be less of a problem with EA (or any other tool) than a design issue.

I don't know offhand how EA handles "Shadows" clauses and such, or other scenarios where this kind of naming conflict comes up. It might be worth looking into this (for me if not for you).

David
No, you can't have it!

Michael McMullin

  • EA Novice
  • *
  • Posts: 6
  • Karma: +0/-0
    • View Profile
Re: Creating a read-only property
« Reply #9 on: August 05, 2007, 10:02:43 am »
In this case, the base class and attribute were named by Microsoft, and I just prefixed the subclass and property with 'My' for testing purposes. However, I do recognize that I've become a little lazy about naming conventions of late, and using EA has certainly helped to focus my attention a lot more.

For private attributes, I use camel case, and for public properties and classes, I use pascal case. I don't usually use prefixes (except an 'I' for interfaces), but the different cases seem to work ok for me. Maybe I should give this a little more thought though.

BTW, I'm not familiar with the term 'Shadows' clauses -- is that the correct name for the scenario I've been describing? For now, I have enough information to proceed, but I'll certainly look into it a bit more.