StrataFrame Forum

Choosing a property of type businesslayer based on the name as a string

http://forum.strataframe.net/Topic26657.aspx

By Charles R Hankey - 3/28/2010

This is one of those things I do instinctively in Fox with Eval() or & and don't quite have the hang of yet in .NET



I have a number of private properties of type businesslayer



_Endorsements

_Premises

_GL

_Propmaster





I get a name ( but getting the displayvalue of an enum BOName ) of a business object.



The properties are named _



Now I want to look at the count of the BO based on the string which have representing



Dim varname as String = "_" & MicroFour.StrataFrame.Tools.Common.GetEnumDisplayValue(bo.BOName)



Lets say varname = "PROPMASTER"



Now I want to get the count of whatever BO is in the property which is in the string varname



i.e. Propmaster.count





Fumbling with syntax here. Appreciate any guidance.



TIA
By Edhy Rijo - 3/28/2010

Hi Charles,



For this kind of VFP EVAL() you have to use System.Reflection, even though I don't quite understand your logic.



I know you want to be able to access a BO instance just know its name or something like that. I think that if you post a quick sample on what you want to accomplish it would be easier.



I know the System.Reflection is the way to get these things done as in VFP EVALUATE() function, but I read many post of developers suggesting to be very careful about using reflection, don't know all the details, but perhaps after knowing more about your logic it could be done without it.
By Edhy Rijo - 3/28/2010

Also if all you want is to get the bo instance based on its name, then you could try code like this:





Dim varname As String = "_Propmaster"

For Each boInForm As MicroFour.StrataFrame.Business.BusinessLayer In Me.BusinessObjects

If boInForm.GetType().Name = varname Then

MessageBox.Show(String.Format("BO Count = {0}", boInForm.Count), "Test")

Exit For

End If

Next





Play with it in the debugger and I am sure you will get what you want. Hehe
By Charles R Hankey - 3/28/2010

Thanks Edhy, I don't think I'm explaining this well



I already have object references to a dozen BOs.



I am evaluating an enum to get a string. Based on that string I want to find the record count of the corresponding BO. I know I can use conditional logic or iterate through the list of BOs but the general technique I'm trying to figure out is the equivalent of



varname = "Propmaster"

bocount= "_"+varname+"1.recordcount"



mycount= eval(bocount)




I thought I had seen a way to do something very close to this in .NET but right now it is eluding me.








By Edhy Rijo - 3/28/2010

Charles,



I know you want to get a direct access like in VFP EVAL() but I am not sure that can be done in .Net. With the code I gave you you can create a function passing the BO type name, do the loop and return the count, assuming you have less than 50 BOs in the form that should be super fast. Tongue
By Charles R Hankey - 3/28/2010

But it is still an issue of manually grinding through a collection of BOs to find a match. I am doing that now and sure it works, but I think I am missing some .NET technique ( reflection? ) where I can do something very close to the eval.



The bos are properties of the method I'm in. (they were passed in as params and assigned to private properties



_Propmaster



etc.



once I have a string "_Propmaster"



It seems I should be able to do something like me.properties("_Propmaster").count




By Charles R Hankey - 3/28/2010

Michel Fournier of the UT was kind enough to lay this function on me which works like a dream. I'll also post it in contributed samples. Very slick and works beautifully :



' Return a reference to a control by the use of its name

' expO1 Form

' expC1 Name of the control

Public Shared Function FindControlByFieldName(ByVal loForm As System.Windows.Forms.Form, ByVal tcProperty As String) As Object

Dim loFieldInfo As System.Reflection.FieldInfo = Nothing

Dim loObject As Object = Nothing

Dim loPropertyInfo As System.Reflection.PropertyInfo = Nothing

Dim loType As System.Type = Nothing



' Get the form type

loType = loForm.GetType()



' Get the property info

loPropertyInfo = loType.GetProperty(tcProperty, System.Reflection.BindingFlags.Public Or _

System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance Or _

System.Reflection.BindingFlags.DeclaredOnly)



' If the property info is known as an object

If Not loPropertyInfo Is Nothing Then

Return loPropertyInfo.GetValue(loForm, Nothing)

End If



' Get the field info

loFieldInfo = loType.GetField(tcProperty, System.Reflection.BindingFlags.Public Or _

System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance Or _

System.Reflection.BindingFlags.DeclaredOnly)



' If the field info is nothing

If loFieldInfo Is Nothing Then

Return Nothing

End If



' Get the field object

loObject = loFieldInfo.GetValue(loForm)



Return loObject

End Function





Now this is all the code I need to accomplish what I want





Dim childname As String = "_" & MicroFour.StrataFrame.Tools.Common.GetEnumDisplayValue(bo.SpilloverGrid)



Dim childbo As BaseBO = CType(FindControlByFieldName(Me, childname), BaseBO)



dim records as Int32 = childbo.count







BigGrin
By Dustin Taylor - 3/29/2010

Nice Smile. Glad you got it figured out!
By Charles R Hankey - 3/29/2010

I should have added in reply to Edhy's earlier post that he is quite right about finding a BO that is part of the BO collection of the form.



This one is a little different in that the BO have been passed into the form as parameters and aren't actually part of the form's BO collection.



I'm sure the function will be useful for other stuff as well, but I have not forgotten the Microfour Mantra that reflection comes with a performance cost and while there is a place for it it should be used carefully and avoided if there is another way to accomplish the same thing without it.



In this case, I couldn't see another way besides a big ugly case statement testing for every possibility of the displayvalue coming from the enum.


By Greg McGuffey - 3/29/2010

I'm not sure I'm following exactly what you need to do here, but assuming that this code occurs within the form that houses the BOs, I wonder if there is a way to go the other way around... When the form initializes, create a dictionary using the enums to reference the BOs. If I used the full class name for the display attribute for each of the enums, then I could do something like this, run in the constructor (unless translations are happening, then I'd do it in OnLoad):



//-- For each BO on the form, get the full name of its type, add to form level dictionary.

For Each bo As BusinessLayer in Me.BusinessObjects

  Dim boTypeName As String = bo.GetType().FullName

  Me.BoDictionary(boTypeName, bo)

Next




Now, my access code is:



Dim childname As String = MicroFour.StrataFrame.Tools.Common.GetEnumDisplayValue(bo.SpilloverGrid)



Dim childbo As BaseBO = Me.BoDictionary(childname)



dim records as Integer= childbo.count




This would work as long as you have only one BO of each type.
By Edhy Rijo - 3/29/2010

Hi Charles,



Glad you found something that works, even though I still don't understand your logic on this one, but if it works that is what matters Tongue



Just to be on the safe side, I noticed that the function or your code does not have any error trapping (TRY/ENDTRY) probably you won't need it, since it looks like those "_" properties are in your base form class, but if for whatever reason a couple of months from now something changes and the property can not be found, your function will return Nothing and your code may fail when you try to access the BO.Count property.