Table Driven Validation?

Table Driven Validation?

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


cruachan posted on Sunday, August 20, 2006

Would it be possible to create a validation object which would cache the validation rules for the system?  For example, this object could be referenced in the AddBusinessRules section of a BusinessBase object, and because the rules are stored in a database table, one could adjust the validation rules without recompiling their applicaiton.

The hard part, is that the handler parameter in the call Validation.AddRule(handler, property) needs to be an actual method, and cannot really be passed as a string value from a table.

Am I wasting my time thinking about this?  Is there a way to satisfy the "handler" parameter above by calling some type of C# function that can return a pointer to a Csla.Validation.RuleHandler from a string search?

I'm a bit new to C#, and even newer to Csla.

Any comments?  Ideas?  Waste of time?  Thanks!

-Cruachan

Skafa replied on Sunday, August 20, 2006

what should be in the string? c# code? some kind of pattern?

you can make a custom validation rule and define a set of rules in your database, which that rule uses.

cruachan replied on Sunday, August 20, 2006

Ok, I think I have answered my question.

I think I was mistaken a bit in my post.  I took a break and realized that I must have been getting tired.

I was working on making the validation and authorization table driven... so, I was trying to load the business rules dynamically at runtime, and realized that I was going to have a problem.  After taking my break, I realized that there was no reason to do that whatsoever...

Although it might be valuable to to change which business rules load or do not load... one shouldn't have a problem getting that done.  For some reason, I was missing the point of what I was trying to do.

I have however, made the Authorization rules of my business objects table driven... all the authorization rules are going to be loaded into another object at runtime... when an object gets created, it will check the authorization object for what fields it has to secure and for what roles.  This way, I can change the roles and fields in the table, and not have to rebuild my app to account for them.

Anyway... looks like I ended up asking a question that was incorrect to begin with.

Thanks,

-cru

david.wendelken replied on Monday, August 13, 2007

cruachan:
Ok, I think I have answered my question.



You might have answered it for YOURSELF, but not for ME!

How did you get ValidationRules.AddRule() to accept the name of a rule from the database?

david.wendelken replied on Tuesday, August 14, 2007

david.wendelken:
cruachan:
Ok, I think I have answered my question.



You might have answered it for YOURSELF, but not for ME!

How did you get ValidationRules.AddRule() to accept the name of a rule from the database?

I spent yesterday trying to figure out the syntax to do this. 

Let's just say that I know a whole lot more about lots of ways that do not work. :(

This appears to be a really nasty syntax problem just waiting for someone to point out an easy, elegant way to do this!

 

david.wendelken replied on Tuesday, August 14, 2007

Ok, here is an example of a failed attempt.  Feel free to provide the solution! :)

(FYI, I have my own common rules library derived from the csla version. 
 Use your own values for typeName.
)

// What we need to create...

// public delegate bool RuleHandler(object target, RuleArgs e);

// A hard-coded way to create it.

// rh = new RuleHandler(CslaSrd.Validation.StdRules.StringRequired);

// Pretend the type and rule come from a database and are loaded into strings...

string typeName = "CslaSrd.Validation.StdRules, CslaSrd, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";

string ruleName = "StringRequired";

// Use Reflection to find the rule method.

Type t = Type.GetType(typeName);

MethodInfo mi = t.GetMethod("StringRequired");

// Use Reflection to find a pointer to the method to create a RuleHandler with.

// Which will fail :( with a "Method Name expected" error.

rh = new RuleHandler( mi.MethodHandle.GetFunctionPointer);

// Add the rule.

ValidationRules.AddRule(rh, "Code");

JoeFallon1 replied on Wednesday, August 15, 2007

David,

I got something to compile. I don't know if it actually works though. Give it a try and let us all know.

'==========================================================================
'hard coded solution works:
'Dim rh As RuleHandler
'rh = New RuleHandler(AddressOf StringRequired)
'ValidationRules.AddRule(rh, "MyProperty")
'==========================================================================

'try strings instead of actual methods and then use reflection:
Dim typeName As String = "My.BO.MyRules, My.BO, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
Dim ruleName As String = "StringRequired"
Dim t As Type = Type.GetType(typeName)
Dim mi As System.Reflection.MethodInfo = t.GetMethod("StringRequired")
Dim rh As RuleHandler
rh =
CType(System.Delegate.CreateDelegate(t, mi), RuleHandler)
ValidationRules.AddRule(rh,
"MyProperty")
'==========================================================================

Joe

david.wendelken replied on Wednesday, August 15, 2007

Joe, you da man!  :)

It wasn't exactly right, but it was close enough to get me to a solution in 15 minutes! :) :) :)

Here's a tested c# version:

string typeName = "My.BO.MyRules, My.BO, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
string ruleName = "StringRequired";

// Use Reflection to find the rule method.
Type t = Type.GetType(typeName);
MethodInfo mi = t.GetMethod("StringRequired");
RuleHandler rh = (RuleHandler)System.Delegate.CreateDelegate(typeof(RuleHandler), mi);
ValidationRules.AddRule(rh, "Code");

In visual basic, I think this line you gave:

rh = CType(System.Delegate.CreateDelegate(t, mi), RuleHandler)

should be:

rh = CType(System.Delegate.CreateDelegate(typeof(RuleHandler), mi), RuleHandler)

 

david.wendelken replied on Wednesday, August 15, 2007

It looks like there may be ways to not have to know the version, culture and publickeytoken in order to get the Type t assigned correctly.  I'll post later when I do some more testing and refactoring.

 

 

JoeFallon1 replied on Wednesday, August 15, 2007

I use code like this to get the type from another assembly:

Private Shared Function GetSomeType() As Type
 
Dim result As Type
 
Dim methodName As String = "someMethod"
  Dim assemblyName As String = "MyAssembly.Namespace"

  'the call to Assembly.Load does nothing extra if the assembly is already loaded.
  'It just returns the loaded assembly.
  Dim loAssembly As System.Reflection.Assembly = System.Reflection.Assembly.Load(assemblyName)
  result = loAssembly.GetType(assemblyName &
"." & methodName )
 
Return result
End Function

Joe

dmccrory replied on Monday, August 13, 2007

cruachan,

 

I am working on the exact type scenario and would be interested in knowing the process you are going to use to accomplish this task. I don't really need details, just an overview of how you think the process will flow....

Copyright (c) Marimer LLC