-
Notifications
You must be signed in to change notification settings - Fork 74
How to correctly implement IDisposable on imported types? #159
Comments
Don't produce close instead of dispose, just put the Close into the Dispose! [Imported]
[IgnoreNamespace]
[ModuleName("sqlite3")]
[ScriptName("Database")]
public class SQLite3Database : IDisposable
{
public delegate void OpenCallback(string error);
public SQLite3Database(string filename, int mode = 0, OpenCallback callback = null) { }
[InlineCode("{this}.close()")]
public void Close() { }
void IDisposable.Dispose()
{
Close();
}
} |
Does not work for me. What code it produces for you? |
The problem is that someone might do
Since I do agree, however, that this is an issue that should be solved in some way, if possible. Any suggestions? |
this using System;
using System.Runtime.CompilerServices;
[Imported]
[IgnoreNamespace]
[ModuleName("sqlite3")]
[ScriptName("Database")]
public class SQLite3Database : IDisposable
{
public delegate void OpenCallback(string error);
public SQLite3Database(string filename, int mode = 0, OpenCallback callback = null) { }
[InlineCode("{this}.close()")]
public void Close() { }
void IDisposable.Dispose()
{
Close();
}
}
public class MainApp
{
[InlineCode("console.log({o})")]
static void Log(object o)
{
}
public static void Main()
{
using (var db = new SQLite3Database(@"c:\Temp\temp.db"))
{
Log("ASD");
}
}
} gets compiled to require('mscorlib');
var sqlite3 = require('sqlite3');
////////////////////////////////////////////////////////////////////////////////
// MainApp
var $MainApp = function() {
};
$MainApp.main = function() {
var db = new sqlite3.Database('c:\\Temp\\temp.db', 0, null);
try {
console.log('ASD');
}
finally {
if (ss.isValue(db)) {
db.dispose();
}
}
};
ss.registerClass(global, 'MainApp', $MainApp);
$MainApp.main(); It just ignores the own defined Dispose function, since it is marked as Imported(or one of the other attributes may influence this behavior) which is a bug in my opinion. using System;
using System.Runtime.CompilerServices;
[Imported]
[IgnoreNamespace]
[ModuleName("sqlite3")]
[ScriptName("Database")]
class JsSQLite3Database
{
public JsSQLite3Database(string filename, int mode = 0, Action<string> callback = null) { }
[InlineCode("{this}.close()")]
public void Close() { }
}
public class SQLite3Database : IDisposable
{
JsSQLite3Database db;
public SQLite3Database(string filename, int mode = 0, Action<string> callback = null)
{
db = new JsSQLite3Database(filename, mode, callback);
}
public void Dispose()
{
if (db != null) {
db.Close();
db = null;
}
}
}
public class MainApp
{
[InlineCode("console.log({o})")]
static void Log(object o)
{
}
public static void Main()
{
using (var db = new SQLite3Database(@"c:\Temp\temp.db"))
{
Log("ASD");
}
}
} The result: require('mscorlib');
var sqlite3 = require('sqlite3');
////////////////////////////////////////////////////////////////////////////////
// MainApp
var $MainApp = function() {
};
$MainApp.main = function() {
var db = new $SQLite3Database('c:\\Temp\\temp.db', 0, null);
try {
console.log('ASD');
}
finally {
if (ss.isValue(db)) {
db.dispose();
}
}
};
////////////////////////////////////////////////////////////////////////////////
// SQLite3Database
var $SQLite3Database = function(filename, mode, callback) {
this.$db = null;
this.$db = new sqlite3.Database(filename, mode, callback);
};
$SQLite3Database.prototype = {
dispose: function() {
if (ss.isValue(this.$db)) {
this.$db.close();
this.$db = null;
}
}
};
ss.registerClass(global, 'MainApp', $MainApp);
ss.registerClass(global, 'SQLite3Database', $SQLite3Database, null, ss.IDisposable);
$MainApp.main(); The benefit is that SQLite3Database is not just some imported class anymore, but a full Saltarelle .NET citizen, which would come in handy if and when other features like reflection get added. |
I have tried to use subclassing: public class SQLite3DatabaseEx : SQLite3Database, IDisposable
{
public SQLite3DatabaseEx(string filename, int? mode = null, SQLite3OpenCallback callback = null)
: base(filename, mode, callback) { }
[InlineCode("{this}.close()")]
void IDisposable.Dispose() { }
} However, it produces the following error:
The problem seems to be here: var $SQLite3_SQLite3DatabaseEx = function(filename, mode, callback) {
sqlite3.Database.call(this, filename, mode, callback);
}; |
Maybe the solution is to use the |
You can't subclass from an imported class. |
You could do something like Perhaps some feature should be added to allow specifying any implementation for |
Yes, that's how I am currently doing it: [InlineCode("{$SQLite3.SQLite3Database}.prototype.dispose = {$SQLite3.SQLite3Database}.prototype.close")]
static void AddDisposeToDatabase() { }
[InlineCode("{$SQLite3.SQLite3Statement}.prototype.dispose = {$SQLite3.SQLite3Statement}.prototype.finalize")]
static void AddDisposeToStatement() { } Why do not allow to subclass from imported class? |
Overloading(especially constructor overloading) and other functionality is handled by registering classes and adhering to specially crafted javascript. Not all imported libraries will conform to this. The shorter answer is: because imported classes won't be registered with ss.registerClass. |
See #405 |
I have the following code:
And I am using it like this:
But it produces the following JavaScript:
I would like to produce
db.close()
instead ofdb.dispose()
. How to achieve that?The text was updated successfully, but these errors were encountered: