Custom rule with a parameter of type ReadOnlyListBase

Custom rule with a parameter of type ReadOnlyListBase

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


lazaroms posted on Friday, November 19, 2010

Hi all:

Can I pass a generic ReadOnlyListBase as a parameter?

I need to implement a custom rule wich has in the ruleargs a ReadOnlyListBase.

It will be a rule to check if the list has an element inside, comparing the Ids.

I have a BO for an user, and the user can work in several offices but not in all offices. Those offices are in a list as a property of the User BO. So the UI can assign and change the office selecting it from the list.

I want to implement a validation rule in order to check that the selected office be a member of the officelist.

My idea is implementing a rule and passing the officelist and office Id as a parameter but and I want to implement a generic rule because it will use in other BO with other lists.

Thanks in advance,

 

Lazaro Manuel

 

RockfordLhotka replied on Friday, November 19, 2010

There's no way to pass parameters to a rule.

Well, that's not strictly true in CSLA 4.

Rules are associated with a type or property at a static level. So you can pass a static parameter - parameter values that are immutable over the entire lifetime of the app, and that can be shared across all instances of business objects using that rule.

So you could pass a list of US state codes for example, because that'd be immutable for the lifetime of the app.

But you couldn't pass a list of region code specific to a division of your sales group, because that could vary during the apps' lifetime.

The thing is, objects that are static and immutable over the app's lifetime don't need to be passed as a parameter, because you usually implement them as cached singletons - so any code can get that object at any time. So there's no reason to ever pass them as a parameter.

JonnyBee replied on Saturday, November 20, 2010

Hi,

Where do you store the User BO?   ApplicationContext.ClientContext or in the Principal object?

I would prefer to allow the rule to get access to the User BO and validate that the value is in the actual list  rather than sending the list as a parameter to the rule.

lazaroms replied on Saturday, November 20, 2010

Thanks for your reponse.

I think I've solved the problem and I'll tell you how, please check my solution and tell me if it well done.

The officelist is a property of my identity object.

I've implemented a rule and I tried to make a generic rule for future uses.

I´ve creted an interface( IExistsIdInList ) for all lists which wants to search for an element via his Idelement. This interface has just one method  (ExistsElement)

So, this is my custom rule.

#Region " ExisteElementInList "

  <System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")> _
  Public Function ExisteElementInList(ByVal target As Object, ByVal e As RuleArgs) As Boolean

    Dim args As ExistsElementInListRuleArgs = CType(e, ExistsElementInListRuleArgs)

    Dim value As Guid = CType((CallByName(target, e.PropertyName, CallType.Get)), Guid)

    Dim mylist As IExistsIdInList = CType((CallByName(target, args.TheList, CallType.Get)), IExistsIdInList)

    If Not mylist.ExistsElement(value) Then

      e.Description = String.Format("{0} " & My.Resources.OwnRules.ExistsElementInListRule, e.PropertyFriendlyName)
      Return False

    Else

      Return True

    End If

  End Function

  Public Class
ExistsElementInListRuleArgs
    Inherits DecoratedRuleArgs

    Public ReadOnly Property TheList() As String
      Get
        Return Me("ListName")
      End Get
    End Property

    Public Sub New(ByVal propertyInfo As Core.IPropertyInfo, ByVal listname As String)
      MyBase.New(propertyInfo)
      Me("ListName") = listname
    End Sub

  End Class

#End Region

Because the Officelist is a property of my identity and implements the IExistsIdInList, I can get the list doing a callbyname. I pass the name of the list inside the ruleargs.

Once I have the office I call his ExistsElement method with the validated property value.

I think this is working fine but a Ihave a new problem. When I run the project VB.NET does not find the resource I use to form the description in case the rule is broken.


 

RockfordLhotka replied on Saturday, November 20, 2010

JonnyBee

Where do you store the User BO?   ApplicationContext.ClientContext or in the Principal object?

Neither.

If the read-only object's factory implements simple static caching like I show in the book, any code anywhere can simply call the factory to get that cached value. No need to store it anywhere else.

You absolutely NEVER want to put something like that in the Principal object - remember that the Principal object is serialized to the server, so that'd have a big perf impact!

lazaroms replied on Monday, November 22, 2010

Sorry friends, when I said User Bo I was referring to my identity object.

Rocky, the office list is not static, is "almost static"  :-) because there's a small probability of an user get authorized/unauthorized to work with an office during life-cycle of the app.

Rocky in what chapter do you talk about simple static caching in the VB 2008 business objects?

Anyways I'll take into account the Rocky observation and I'll implement a function to return the officelist when needed.

Thanks,

 

Lazaro Manuel

 


RockfordLhotka replied on Monday, November 22, 2010

I don't know - I've talked about static caching so often it is hard to remember. It isn't hard, this is the factory method section:

private MyType _cache;

public static void ClearCache()
{
  _cache = null;
}

public static GetMyType()
{
  if (_cache == null)
    _cache = DataPortal.Fetch<MyType>();
  return _cache;
}

 

lazaroms replied on Monday, November 22, 2010

Thanks Rocky.

 

Page 556

Copyright (c) Marimer LLC