Accessing property values in F# constructors - constructor

Sorry if this is basic, but I'm still wrapping my head around F#.
I want to do this:
type Person(user:User) as this =
member val Name = "" with get, set
user.UserId <- this.Name
But that gives me the error Unexpected identifier in member definition.
This compiles:
type Person(user:User) as this =
do
user.UserId <- this.Name
member val Name = "" with get, set
But gives me an InvalidOperationException at runtime.
I've settled for this:
type Person(user:User) =
member val Name = "" with get, set
member this.Setup() =
user.UserId <- this.Name
But I don't like having to call person.Setup() each time.
What's the best F-Sharpy way to do this?

You can do this with an explicit constructor to force the code for initializing the member functions to be run before your other code as follows
type User() =
member val UserId = "" with get,set
type Person private () =
member val Name = "" with get, set
new (user:User) as this =
Person()
then user.UserId <- this.Name
This is due to the fact that the initializer code is run in the constructor, so you must force it to run to completion before acccessing the properties

Related

Android Room Kotlin: entities with non data classes

Regarding to classes that can/may be used for entities in room whith Kotlin,
Is it mandatory to use data classes? Or could I use 'normal classes', i.e., the ones I use for the 'bussiness logic'
In case data classes are mandatory: can I add functionality to what they have by default? i.e, can I add functions (for whatever taks they may need) to them?
The documentation doesn't say anything about limiting entities to data classes (although each and every code snippet use a data class).
Thanks.
Is it mandatory to use data classes?
No, you can use either including a mix.
data classes are a convenience class
can I add functionality to what they have by default?
Yes.
Perhaps consider the following:-
#Entity
class Table1 {
#PrimaryKey
var id: Long? = null
var name: String = ""
#Ignore
var notAColumnInTheTable = false
constructor(){}
#Ignore
constructor(name: String) {
this.id = null
this.name = name
this.notAColumnInTheTable = true
}
fun getIdAndName(): String {
return id.toString() + ":" + name
}
}
and :-
#Entity
data class Table2(
#PrimaryKey
var id: Long? = null,
var name: String,
#Ignore
var notAColumnInTheTable: Boolean = false
) {
constructor(name: String) : this( id = null,name = name, notAColumnInTheTable = true)
fun getIdAndName(): String {
return id.toString() + ":" + name
}
}
basically they are the same.
Using :-
#Dao
abstract class Table1And2Dao {
#Insert
abstract fun insert(table1: Table1): Long
#Insert
abstract fun insert(table2: Table2): Long
#Query("SELECT * FROM table1")
abstract fun getAllFromTable1(): List<Table1>
#Query("SELECT * FROM table2")
abstract fun getAllFromTable2(): List<Table2>
}
note the use of an abstract class rather than the normally see interface
along with a suitable #Database annotated class, in this case one that has a function that returns an instance of the built database and for convenience/brevity allows running on the main thread.
Then using :-
var db = AppDatabase.getDatabase(this)
var dao = db.getTable1AndTable2Dao()
dao.insert(Table1("TABLE1_1"))
dao.insert(Table2("TABLE2_1"))
for(t1: Table1 in dao.getAllFromTable1()) {
Log.d("DBINFO","Name is ${t1.name} ID is ${t1.id} NotAColumnInTable is ${t1.notAColumnInTheTable} idandname = ${t1.getIdAndName()}")
}
for(t2: Table2 in dao.getAllFromTable2()) {
Log.d("DBINFO","Name is ${t2.name} ID is ${t2.id} NotAColumnInTable is ${t2.notAColumnInTheTable} idandname = ${t2.getIdAndName()}")
}
Results in the log including:-
D/DBINFO: Name is TABLE1_1 ID is 1 NotAColumnInTable is true idandname = 1:TABLE1_1
D/DBINFO: Name is TABLE2_1 ID is 1 NotAColumnInTable is true idandname = 1:TABLE2_1
Via App Inspection :-
and :-

Does Flash have a method that does the reverse of toString?

When using ObjectUtil there is a method called, toString() that takes an object. If you pass it a class named, "Person" it will return the string "[class Person]".
var person:Person = new Person();
trace(ObjectUtil.toString(person));//UPDATE I'm not using ObjectUtil.toString()
// traces [class Person]
Is there a toObject() method? Something that takes the same format toString outputs and creates an instance like so:
var person:Person = ObjectUtil.toObject("[class Person]");
UPDATE:
Sorry. This is incorrect. I thought I was using ObjectUtil.toString(). I was not. When I use that method it returns something like:
(com.printui.assets.skins::fontList)#0
accessibilityDescription = ""
accessibilityEnabled = true
accessibilityImplementation = (null)
In my code somewhere it is returning "[class Person]" like I was described. This is the line:
var currentValue:* = target[property];
popUpValueInput.text = currentValue;
I thought it was using instance.toString() but toString() is not returning anything close to that:
var f:fontList = new fontList();
var f1:fontList = new fontList();
trace("" + f);
trace("" + f1);
trace(f1.toString());
Results in:
fontList2
fontList5
fontList5
In general you should do this:
In your Person class add this method:
public function toString():String
{
return "Person" ;
}
So to make an instance of the class by name use this code:
var p = new (getDefinitionByName( ObjectUtils.toString(person)))
or it can be used a regex in general for all classes (thanks to 1.21 gigawatts ):
var p = new (getDefinitionByName( ObjectUtil.toString(Person).match(/\((.*)\)/)[1] ) );

how to let jsontypeinfo return null on unknown type?

I have code like the following.
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true, defaultImpl = Default.class)
#JsonSubTypes({
#Type(value = T1.class, name = "t1"),
#Type(value = T2.class, name = "t2"),}
)
public abstract class T{
}
the other class may book like
class Foo{
T t;
T anotherT;
}
However, it will return an instance of Default if type in unknown. If i did not specify defaultImp, jackson just throw an exception.
Could not resolve type id 't3' into a subtype of T
I have DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES set to false already.
What I need is if type is not 't1' or 't2', just set the value to null, and continue parsing.
How can I do it?
Thanks

How to have a field member which is persisted in another schema?

Assume the following (I'm using MySQL)
#PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class TclRequest2 {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private long id;
#Persistent(column = "userid")
#Column(jdbcType = "INTEGER", length = 11, allowsNull = "false", defaultValue = "1")
private Member member; // This object table is in another schema
// Getters and setters
}
The field member is persisted in another schema. I could solve this by specifying the "catalog" attribute in the Member class's #PersitentCapable annotation but that would kill the flexibility of specifying the schema name in the properties file I'm using since I'm configuring jdo in a properties file.
Thank you.

capture output parameter from stored proc in LINQ To SQL ExecuteQuery

Is it possible to get an output parameter back from the LINQ To SQL DataContext when you execute a stored procedure?
IEnumerable<Address> result =
ExecuteQuery<Address>(((MethodInfo)(MethodInfo.GetCurrentMethod())),
address, pageIndex, pageSize, totalCount);
where address, pageIndex and pageSize are input parameters, and TotalCount is an output parameter.
How can you capture the output param?
here is another attempt at doing it but again cannot get the parameter value:
[Function(Name = "Telecom.AddressSearch")]
private IEnumerable SearchAddress([Parameter(Name = "address", DbType = "varchar")] string address,
[Parameter(Name = "pageIndex", DbType = "int")] int pageIndex,
[Parameter(Name = "pageSize", DbType = "int")] int pageSize,
[Parameter(Name = "totalCount", DbType = "int")] ref int totalCount)
{
IEnumerable result = ExecuteQuery(((MethodInfo)(MethodInfo.GetCurrentMethod())), address, pageIndex, pageSize, totalCount);
return result;
}
Scott Guthrie has a blog post that describes how to get LINQ to SQL to work with stored procedures. While his post does not directly answer your question, it provides a clue to something that may work. When defining a method in a .dbml class, "LINQ to SQL maps 'out' parameters in SPROCs as reference parameters (ref keyword)." You might try and use the ref keyword and see if the totalCount gets updated.
IEnumerable r = ExecuteQuery(((MethodInfo)(MethodInfo.GetCurrentMethod())),
address, pageIndex, pageSize, ref totalCount);
Update:
I did some more research, and have found a way that should work for you. This is from an MSDN article. You would need to extend your DataContext, but that shouldn't be too big of an issue (it appears you may already be doing this). Check out the article for more information, but the basic piece is this:
[Function(Name="dbo.CustOrderTotal")]
[return: Parameter(DbType="Int")]
public int CustOrderTotal([Parameter(Name="CustomerID", DbType="NChar(5)")] string customerID, [Parameter(Name="TotalSales", DbType="Money")] ref System.Nullable<decimal> totalSales)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), customerID, totalSales);
totalSales = ((System.Nullable<decimal>)(result.GetParameterValue(1)));
return ((int)(result.ReturnValue));
}
Where 'this' is your DataContext.
Update 2:
The IExecuteResult has a ReturnValue property. It is of type Object, so you will have to cast it to get the results, but it should allow you to get the Enumerable of the results. In your case, something like this should work:
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), address, pageIndex, pageSize, totalCount);
totalCount = ((System.Nullable<decimal>)(result.GetParameterValue(3)));
return (IEnumerable<Address>)result.ReturnValue;