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!
thanks Rocky !!
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".
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.
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.
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
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.
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<object> GetChildren();
}
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
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.
Hi Rocky,
Do you mean editing
Csla.Core.BusinessBase
and replacing
List<IPropertyInfo> IManageProperties.GetManagedProperties()
by
/// <summary> /// Gets the managed properties collection. /// </summary> /// <returns>The managed properties collection.</returns> [EditorBrowsable(EditorBrowsableState.Advanced)] public List<IPropertyInfo> GetManagedProperties()
Regards
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.
Interesting idea.
Are they allowed to submit the code to CSLA?
Did they include ALL public methods?
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?).
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;
}
Yes, that is what I was thinking.
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);
}
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.
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.
Good, I'll do it in a short time.
Checked in for both CSLA 4.3 and 4.5
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,
Does it conflicts with the changing of GetManagedProperties() method visibility?
I haven't figured out which interface should get that method yet.
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.
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
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
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.
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