Hi,
We're currently using CSLA version 1.0. We're in the process of converting a couple of apps to 2.0.
We'd like to modify BusinessBase (in both versions, if possible) just a bit to allow for a Custom Attribute to be defined for classes which derive from BusinessBase. This attribute would be used to define a "Friendly Name" for the class. This seems to be simple enough to do, for instances of derived classes, via code in BusinessBase like:
-----
Public ReadOnly Property FriendlyName() As String Get Dim classtype As Type = Me.GetType Dim attr As FriendlyNameAttribute = DirectCast(Attribute.GetCustomAttribute(classtype, GetType (FriendlyNameAttribute)), FriendlyNameAttribute) If attr IsNot Nothing Then Return attr.FriendlyName Else Return classtype.Name End If End Get End Property-----
where FriendlyNameAttribute is a straightforward attribute class implementing a FriendlyName string property, and the derived class's definition is decorated appropriately with the FriendlyName attribute.
The problem is that we'd like to be able to access this attribute via a shared method in BusinessBase. This is because there are situations where no instance of the derived class may be available, but we'd still like to display something in the UI using the "Friendly Name" of that class. For example, it may not be possible to create an instance of the class (e.g, because some error has occurred, or the user is not authorized to do so, etc.), so we'd like to display an informational message with a more user friendly description of the class which is at the root of whatever the problem may be.
For example, as a programmer I might define a class called EntLOB. A more friendly name for this class might be "Enterprise Line of Business". Thus I'd like the error display to read something like:
Unable to retrieve the Enterprise Line of Business because ...
rather than
Unable to retrieve the EntLOB because ...
Creating the error string might be done as :
errormsg = string.format("Unable to retrieve the {0} because ...", SomeEntLOB.FriendlyName, ...) ...
I would define the derived class like:
<Serializable, FriendlyName("Enterprise Line of Business")> _
Public Class EntLOB
Inherits BusinessBase ...
As I said, this all works when I have an instance, but if I try to define the FriendlyName property in BusinessBase as shared, of course, the Me.GetType no longer works.
The creation of the error message when there is no instance presumably would be:
errormsg = string.format("Unable to retrieve the {0} because ...", EntLOB.FriendlyName, ...) ...
So, the question is, is it possible to use reflection in a shared method in a base class to retrieve an attribute which decorates the class definition on a derived class of that base? Sure feels like I ought to be able to do that, but I just don't see how.
Thanks for any help and insight anyone can offer.
Hi Brian,
Thanks for your reply.
As I stated in my original post, my problem is that I may not have an instance of the derived class to get its Type (if I do, this is easy and my problem goes away). The method in BusinessBase (or elsewhere) would have to be shared, and I can't figure out what sort of reflection incantation I need to get the type of a derived class from within that shared method.
It turns out that we originally dealt with this by defining a MustImplement property in BusinessBase. This seems to me, on some level, to be equivalent to your suggestion of using a string resource by the typename. The author of a derived class is then required to implement the FriendlyName method that BusinessBase insisted on. That was OK, but we found that in the majority of the classes that we defined, the Friendly Name was the same as the class name (e.g. Customer). Thus, most of our class definitions were "cluttered" with what appeared to be redundant FreindlyName property implementations.
Assuming I can get the type name of the derived class, then it seems to me that the string resource would also be "cluttered" with redundant entries in a similar way.
I came up with the bright idea of a Custom Attribute, and figured that the developer would only need to provide the attribute in the case where the Friendly Name was different than the class name. The implementation of (my modified) BusinessBase's FriendlyName would return the Type's ClassName property in the case where no attribute was defined.
Works great when I have an instance of the derived class. I can't figure out how to do it when there is none...
But this FriendlyName method would be implemented in BusinessBase.
I certainly can't encode a GetType() in that method for all the classes which might inherit from BusinessBase...
Is there no way to use reflection in a base class to get the Type of a class derived from that base when there is no instance of the derived class, i.e in a shared method of the base?
jemmer:But this FriendlyName method would be implemented in BusinessBase.
I certainly can't encode a GetType() in that method for all the classes which might inherit from BusinessBase...
Is there no way to use reflection in a base class to get the Type of a class derived from that base when there is no instance of the derived class, i.e in a shared method of the base?
Copyright (c) Marimer LLC