Rule FriendlyName property

Rule FriendlyName property

Old forum URL: forums.lhotka.net/forums/t/3424.aspx


ReadOnlyChild posted on Saturday, August 25, 2007

Hello, I see how the friendlyName can be obtained thru the static method in RuleArgs, and can be accessed on the validator method to assign the Description property on the "validator" method;

I would benefit if the friendlyName property could also be obtained at the time of displaying the BrokenRuleCollection on an BO, for instance dataBind-ing this collection to a dataGridView in UI.

my question is if it would be a good idea to implement the FriendlyName in the BrokenRule class and somehow pass it along from the RuleArgs class..., any suggestions are appreciated !!!

saludos!

RockfordLhotka replied on Monday, August 27, 2007

Interesting idea - I'll add it to the wish list.

ReadOnlyChild replied on Tuesday, August 28, 2007

thanks Rocky !!

Big Smile [:D]

tiago replied on Sunday, April 29, 2012

ReadOnlyChild

Hello, I see how the friendlyName can be obtained thru the static method in RuleArgs, and can be accessed on the validator method to assign the Description property on the "validator" method;

I would benefit if the friendlyName property could also be obtained at the time of displaying the BrokenRuleCollection on an BO, for instance dataBind-ing this collection to a dataGridView in UI.

my question is if it would be a good idea to implement the FriendlyName in the BrokenRule class and somehow pass it along from the RuleArgs class..., any suggestions are appreciated !!!

saludos!

Hi Rocky,

Working on CslaActionExtender I have the same requisite: display the OriginPropertyFriendlyName. When I show the broken rules using ErrorWarnInfo object, I don't need to include the OriginPropertyFriendlyName as this controls shows next to the visual element and adding this friendly name would be just "noise".

RockfordLhotka replied on Sunday, April 29, 2012

The broken rules collection is serialized with the object, so each broken rule object must be as small as possible. I have no problem adding a helper property the retrieves the friendly name, but I wouldn't want to store that value in the broken rule object itself.

JonnyBee replied on Sunday, April 29, 2012

Hi Tiago,

No - I do not believe that you should present the OriginPropertyFriendlyName. OriginProperty is more for internal usage and how the RuleEngine runs cleanup of validation rules before executing. IE: A rule can call AddXYZResult to set reult on other properties than the PrimaryProperty. These BrokenRule will always have another PrimaryProperty to which it should be displayed - but in these circumstances the OriginProperty is the PrimaryProperty for that rule and NOT the property that the message belongs to.

You should use PrimaryProperty and maybe add a Extension method to BrokenRule that gets the FriendlyName.

 

 

tiago replied on Sunday, April 29, 2012

Hi Rocky and Jonny,

As the property's FriendlyName is part of the BO, there is no point in duplicating that piece of information. My first approach was to try to get that value. When I found no method to do it, I turned to plan B and add it to the broken rule object.

I suppose that adding this method to BusinessBase.cs will do it

    #region GetPropertyFriendlyName
 
    /// <summary>
    /// Gets a property's friendly name.
    /// </summary>
    /// <param name="propertyName">The name of the property.</param>
    /// <returns>The property's friendly name.</returns>
    public string GetPropertyFriendlyName(string propertyName)
    {
      var propertyInfo = FieldManager.GetRegisteredProperties().Where(c => c.Name == propertyName).FirstOrDefault();
      if (propertyInfo == null)
        throw new ArgumentOutOfRangeException("propertyName");
 
      return propertyInfo.FriendlyName;
    }
 
    #endregion

RockfordLhotka replied on Tuesday, May 08, 2012

Due to some pressing family issues I have been unable to really look at this in depth until now.

The solution should be to take the GetManagedProperties method implemented today for the IManageProperties interface, and to make that public. That would allow UI components like CslaActionExtender to gain access to the IPropertyInfo objects for all registered properties.

The IPropertyInfo objects already have the friendly name as a property, along with other potentially useful information.

The only risk in this, is that external code can change the Index property, and if that occurs they'd introduce nasty serialization errors (and probably other errors). But the IPropertyInfo objects are normally already public and can be found using normal reflection, so I don't see this as an increased risk over today.

JonnyBee replied on Tuesday, May 08, 2012

Hmmmmm,

Do we really want to make the entire IManagePoperties interface avalible publicly to external code?

  internal interface IManageProperties
  {
    bool HasManagedProperties { get; }
    bool FieldExists(Csla.Core.IPropertyInfo property);
    List<IPropertyInfo> GetManagedProperties();
    object GetProperty(IPropertyInfo propertyInfo);
    object ReadProperty(IPropertyInfo propertyInfo);
    P ReadProperty<P>(PropertyInfo<P> propertyInfo);
    void SetProperty(IPropertyInfo propertyInfo, object newValue);
    void LoadProperty(IPropertyInfo propertyInfo, object newValue);
    void LoadProperty<P>(PropertyInfo<P> propertyInfo, P newValue);
    List<objectGetChildren();
  }

ReadProperty/LoadProperty/.... is at current version protected methods only and thus available to class and descendants.

PropertyInfo<T>.Index should marked with

    [EditorBrowsable(EditorBrowsableState.Never)]
    int Core.IPropertyInfo.Index

 

 

RockfordLhotka replied on Tuesday, May 08, 2012

No, absolutely not!

I am only suggesting making the GetManagedProperties method public so it is available through the interface and directly. Probably with EditorBrowsable(Advanced) to avoid some API clutter.

tiago replied on Saturday, May 19, 2012

Hi Rocky,

Do you mean editing

Csla.Core.BusinessBase

and replacing

List<IPropertyInfoIManageProperties.GetManagedProperties()

by

    /// <summary>
    /// Gets the managed properties collection.
    /// </summary>
    /// <returns>The managed properties collection.</returns>
    [EditorBrowsable(EditorBrowsableState.Advanced)]
    public List<IPropertyInfoGetManagedProperties()

Regards

RockfordLhotka replied on Saturday, May 19, 2012

Well actually I was talking to Jason Bock on the way back from VS Live NY earlier this week and he had a good idea.

What they've done on his current project is to define a consolidated public IBusinessBase interface that exposes all the standard public methods from BusinessBase in one interface. They did this to make some mocking and testing scenarios simpler.

But even outside mocking/testing, the value of implementing this consolidated interface is that a UI framework component (like CslaActionExtender) would have easy access to all these elements through the interface - and without adding more elements to the default public interface of the object.

JonnyBee replied on Sunday, May 20, 2012

Interesting idea. 

Are they allowed to submit the code to CSLA? 

Did they include ALL public methods? 

RockfordLhotka replied on Sunday, May 20, 2012

No, they can't contribute the code. But really, there's not much code to contribute, because all they did was define an interface against pre-existing methods/interfaces.

I think the only thing that wasn't easy was getting at the broken rules collection, because that's not part of an existing public interface. I think it probably should be part of some existing public interface though, so fixing that doesn't seem like a bad thing to me (ICheckRules perhaps?).

JonnyBee replied on Monday, May 21, 2012

BusinessBase has BrokenRulesCollection as a virtual property and Interface does not accept properties.

But we could add a new method to ICheckRules as GetBrokenRules() and return that property.

    /// <summary>
    /// Gets the broken rules for this object
    /// </summary>
    BrokenRulesCollection ICheckRules.GetBrokenRules()
    {
      return BrokenRulesCollection;
    }

RockfordLhotka replied on Monday, May 21, 2012

Yes, that is what I was thinking.

JonnyBee replied on Monday, May 21, 2012

Should CSLA.Core.BusinessBase.cs expose the method as

    public BrokenRulesCollection GetBrokenRules()
    {
      return BrokenRulesCollection;
    }

or only through interface

    BrokenRulesCollection ICheckRules.GetBrokenRules()
    {
      return BrokenRulesCollection;
    }

or just return an IEnumerable

    IEnumerable<BrokenRule> ICheckRules.GetBrokenRules()
    {
      return Enumerable.ToArray(BrokenRulesCollection);
    }

RockfordLhotka replied on Monday, May 21, 2012

No, we actually want to return the real list. It is designed for this purpose, and so is read-only for external consumers.

The reason for exposing the real list, is that it is a bindable list, so a UI developer can bind it to a control on the screen so the user sees the list of broken rules as they occur.

RockfordLhotka replied on Monday, May 21, 2012

The method is currently a public virtual method, and that shouldn't change. I don't want to create a breaking change out of this, just add the method to the ICheckRules interface.

JonnyBee replied on Monday, May 21, 2012

Good, I'll do it in a short time.

JonnyBee replied on Monday, May 21, 2012

Checked in for both CSLA 4.3 and 4.5

http://www.lhotka.net/cslabugs/edit_bug.aspx?id=1052

tiago replied on Monday, May 21, 2012

Hi Jonny,

Got the changes.Besides adding a method GetBrokenRules() to ICheckRules I really fail to see the point of this change. This method duplicates the public virtual BrokenRulesCollection property (the difference is that you can't be override it).

As it is, I'm not any closer to get the property FriendlyName. I hope the "consolidated public IBusinessBase interface" Rocky mentions some messages back will help in that particular.

Regards,

tiago replied on Monday, May 21, 2012

Does it conflicts with the changing of GetManagedProperties() method visibility?

RockfordLhotka replied on Monday, May 21, 2012

I haven't figured out which interface should get that method yet.

JonnyBee replied on Monday, May 21, 2012

Hi Tiago,

You cannot have properties in an interface - only methods, delegates and events.

From MSDN:http://msdn.microsoft.com/en-us/library/87d83y5b%28v=vs.100%29.aspx

An interface contains only the signatures of methods, delegates or events. The implementation of the methods is done in the class that implements the interface, as shown in the following example:

So the purpose is to create a method in an interface (in CSLA or your own Interface as previous in the discussion) that can be mocked easily.

 

 

tiago replied on Tuesday, May 22, 2012

Hi Jonny,

Something weird is hapening as my browser shows me a totally different text

An interface contains only the signatures of methods, properties, events or indexers. A class or struct that implements the interface must implement the members of the interface that are specified in the interface definition.

Regards

tiago replied on Tuesday, May 22, 2012

Hi again,

Google is my friend and searching for your text pointed me to the VS2005 page.

http://msdn.microsoft.com/en-us/library/87d83y5b(v=vs.80).aspx

 

 

Nevertheless, a few paragraphs below the same page states:

Remarks


An interface can be a member of a namespace or a class and can contain signatures of the following members:

RockfordLhotka replied on Tuesday, May 22, 2012

Actually I have decided on a different solution to the GetRegisteredProperties issue.

If you think about it, CSLA has its own "type system" using registered properties. This type system is managed by the PropertyInfoManager type in Csla.Core.FieldManager.

That type is current internal, but could be public, with only one public member: GetRegisteredProperties.

    /// <summary>
    /// Returns a copy of the property list for
    /// a given business object type. Returns
    /// null if there are no properties registered
    /// for the type.
    /// </summary>
    /// <param name="objectType">
    /// The business object type.
    /// </param>
    /// <remarks>
    /// Registered property information is only available after at least one instannce
    /// of the object type has been created within the current AppDomain.
    /// </remarks>
    public static PropertyInfoList GetRegisteredProperties(Type objectType)

This change will make the type information available to any code in the application, and without the need for an instance of the business object (though at least one instance must have been created prior to invoking this method).

I like this approach because it avoids cluttering the BusinessBase API, and more closely follows the model of the .NET type system.

tiago replied on Tuesday, May 22, 2012

Hi Rocky,

I can see you posted the changes. I'm posting the updated code for CslaActionExtender and CslaActionExtenderTsb right away.

Regards,

Copyright (c) Marimer LLC