Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: VB.NET: [VB2008] Asetus suoraan omalla tyypillä

vesimies [23.03.2009 18:52:02]

#

Moi,

yritän tässä tallentaa asetuksia My.Settings-systeemillä, mutta on pientä ongelmaa.

En saa millään tehtyä asetusta, jonka tyyppi on itse tekemäni luokka, niin että se luokka on määritelty samassa projektissa. Jos se on määritelty toisessa projektissa niin asetuksen tyypin valinta onnistuu (kunhan laittaa referenssin tietysti).

Tässä pieni esimerkki siitä miltä homma näyttää. Sanotaan projekteja vaikkapa PääProjektiksi ja SivuProjektiksi.

SivuProjektissa määritelty luokka:

<Serializable()> Public Class EräsLuokka
    Protected nimi As String
    Protected ikä As Single

    Public Sub New(ByVal nimensä As String, ByVal ikänsä As Single)
        nimi = nimensä
        ikä = ikänsä
    End Sub

    Public Overrides Function ToString() As String
        Return nimi & ", " & CStr(ikä) & " vuotta"
    End Function
End Class

Sitten PääProjektissa:

Project -> Properties -> Settings. Tehdään asetus nimeltä OletusHenkilö ja valitaan sen tyypiksi EräsLuokka.

Testataan esim. Form-loadissa:

Dim hlö As New EräsLuokka("Matti", 32.56!)
My.Settings.OletusHenkilö = hlö
Dim hänTakaisin As EräsLuokka = My.Settings.OletusHenkilö
MsgBox(hänTakaisin.ToString)

Tulostaa: "Matti, 32,56 vuotta"

Tässäkin on sellainen ongelma että se ei toimi oikeasti. Esim:

Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    My.Settings.OletusHenkilö = New EräsLuokka("Masa", 41.78)
    My.Settings.Save()
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim hlö As EräsLuokka = My.Settings.OletusHenkilö
    ' Tulee Nothing vaikka on kyllä tallennettu!
    MsgBox(hlö.ToString) ' tulee virhe
    ' (tämä täytyy ajaa ensin kertaalleen ilman tuota MsgBox-riviä)
End Sub

Eli kaksi kysymystä:
Miten Serializable saadaan oikeasti toimimaan?
Miten omat tyypit saadaan näkymään saman projektin asetustaulukossa?

neau33 [24.03.2009 14:06:21]

#

No moro!

Et viittis Copy/Pastettaa Projektisi Properties-kansiosta Settings.setting & Setting.Designer.vb filujen sisältöä näkösälle..?

vesimies [24.03.2009 16:01:53]

#

OK, tässä tulee. Jostain syystä tosin en enää edes saanut valittua sitä omaa tyyppiä, kun testailin muita tyyppejä (menee aina vaan hämärämmäksi). Muutin tähän OletusHlö-asetuksen tyypin käsin jotta siitä näkyy se oikea tyyppi. Tämä on tällainen sekava testiprojekti, noilla asetuksilla ei ole mitään oikeaa merkitystä.

Toivottavasti tajusin nyt oikein mitä tiedostoja tarkoitit.

Settings.vb: (Settings.settings -> View code)

Namespace My
    'This class allows you to handle specific events on the settings class:
    ' The SettingChanging event is raised before a setting's value is changed.
    ' The PropertyChanged event is raised after a setting's value is changed.
    ' The SettingsLoaded event is raised after the setting values are loaded.
    ' The SettingsSaving event is raised before the setting values are saved.
    Partial Friend NotInheritable Class MySettings
    End Class
End Namespace

Settings.Designer.vb:

'------------------------------------------------------------------------------
' <auto-generated>
'     This code was generated by a tool.
'     Runtime Version:2.0.50727.3053
'
'     Changes to this file may cause incorrect behavior and will be lost if
'     the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
Namespace My
    <Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.System.CodeDom.Compiler.GeneratedCodeAttribute( _ "Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0"), _
Global.System.ComponentModel.EditorBrowsableAttribute( _ Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
    Partial Friend NotInheritable Class MySettings
        Inherits Global.System.Configuration.ApplicationSettingsBase
        Private Shared defaultInstance As MySettings =
CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings)

#Region "My.Settings Auto-Save Functionality"
#If _MyType = "WindowsForms" Then
        Private Shared addedHandler As Boolean
        Private Shared addedHandlerLockObject As New Object
        <Global.System.Diagnostics.DebuggerNonUserCodeAttribute(),
Global.System.ComponentModel.EditorBrowsableAttribute( _ Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
        Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs)
            If My.Application.SaveMySettingsOnExit Then
                My.Settings.Save()
            End If
        End Sub
#End If
#End Region

        Public Shared ReadOnly Property [Default]() As MySettings
            Get
#If _MyType = "WindowsForms" Then
                If Not addedHandler Then
                    SyncLock addedHandlerLockObject
                        If Not addedHandler Then
                            AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings
                            addedHandler = True
                        End If
                    End SyncLock
                End If
#End If
                Return defaultInstance
            End Get
        End Property

        <Global.System.Configuration.UserScopedSettingAttribute(), _
         Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
         Global.System.Configuration.DefaultSettingValueAttribute("00:00:00")> _
        Public Property Kello() As Global.System.TimeSpan
            Get
                Return CType(Me("Kello"), Global.System.TimeSpan)
            End Get
            Set(ByVal value As Global.System.TimeSpan)
                Me("Kello") = value
            End Set
        End Property

        <Global.System.Configuration.UserScopedSettingAttribute(), _
         Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
         Global.System.Configuration.DefaultSettingValueAttribute("0")> _
        Public Property Lintuja() As Long
            Get
                Return CType(Me("Lintuja"), Long)
            End Get
            Set(ByVal value As Long)
                Me("Lintuja") = value
            End Set
        End Property

        <Global.System.Configuration.UserScopedSettingAttribute(), _
         Global.System.Diagnostics.DebuggerNonUserCodeAttribute()> _
        Public Property OletusFontti() As Global.System.Drawing.Font
            Get
                Return CType(Me("OletusFontti"), Global.System.Drawing.Font)
            End Get
            Set(ByVal value As Global.System.Drawing.Font)
                Me("OletusFontti") = value
            End Set
        End Property

        <Global.System.Configuration.UserScopedSettingAttribute(), _
         Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
         Global.System.Configuration.DefaultSettingValueAttribute("")> _
        Public Property OletusHlö() As Global.Laskujuttuja.EräsLuokka
            Get
                Return CType(Me("OletusHlö"), Global.Laskujuttuja.EräsLuokka)
            End Get
            Set(ByVal value As Global.Laskujuttuja.EräsLuokka)
                Me("OletusHlö") = value
            End Set
        End Property
    End Class
End Namespace

Namespace My
    <Global.Microsoft.VisualBasic.HideModuleNameAttribute(),  _
     Global.System.Diagnostics.DebuggerNonUserCodeAttribute(),  _
     Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute()>  _
    Friend Module MySettingsProperty

<Global.System.ComponentModel.Design.HelpKeywordAttribute("My.Settings")>  _
        Friend ReadOnly Property Settings() As Global.Testejä.My.MySettings
            Get
                Return Global.Testejä.My.MySettings.Default
            End Get
        End Property
    End Module
End Namespace

vesimies [25.03.2009 13:26:21]

#

Tässä vielä Settings.settings -tiedoston varsinainen sisältö (avasin Notepadilla), kun en eilen tajunnut tätä kaivaa esiin. Tässä on OletusHlö-asetuksen tyyppi väärin mutta ei haitanne.

<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="My" GeneratedClassName="MySettings" UseMySettingsClassName="true">
  <Profiles />
  <Settings>
    <Setting Name="Kello" Type="System.TimeSpan" Scope="User">
      <Value Profile="(Default)">00:00:00</Value>
    </Setting>
    <Setting Name="Lintuja" Type="System.Int64" Scope="User">
      <Value Profile="(Default)">0</Value>
    </Setting>
    <Setting Name="OletusFontti" Type="System.Drawing.Font" Scope="User">
      <Value Profile="(Default)" />
    </Setting>
    <Setting Name="OletusHlö" Type="System.String" Scope="User">
      <Value Profile="(Default)" />
    </Setting>
  </Settings>
</SettingsFile>

Unohdin mainita että käytössä on Express Edition. Onko merkitystä tässä asetusten käyttämisessä?

Edit: Laitan tähän vielä user.config-tiedoston johon ne asetukset tallentuvat. Huomasin että yleensä siellä näkyy olevan

serializeAs="String"

ja että jos asetuksen tyypiksi onnistuu valitsemaan oman tyypin (laitoin nyt Form1 koska muuta omaa tyyppiä en onnistunut valitsemaan), niin tuleekin

serializeAs="Xml"

user.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <userSettings>
        <Testejä.My.MySettings>
            <setting name="Kello" serializeAs="String">
                <value>15:47:58</value>
            </setting>
            <setting name="Lintuja" serializeAs="String">
                <value>500</value>
            </setting>
            <setting name="OletusHlö" serializeAs="Xml">
                <value />
            </setting>
            <setting name="OletusFontti" serializeAs="String">
                <value>Microsoft Sans Serif, 8.25pt</value>
            </setting>
        </Testejä.My.MySettings>
    </userSettings>
</configuration>

Edit2: Juuri tuolta se user.config-tiedosto näytti OletusHlö-kohdan osalta, kun olin suorittanut nämä rivit:

My.Settings.OletusHlö = New EräsLuokka("Masa", 41.78)
My.Settings.Save()

Eli ei sinne tallentunut yhtään mitään. Sen sijaan kaikki valmiit tyypit tallentuu ilman mitään ongelmia kuten näkyykin.

vesimies [25.03.2009 21:30:25]

#

Pitkällisen "kokeile kaikkea mahdollista" -tyyppisen testailun tuloksena sain tämän viimein toimimaan.

Näyttää siltä että nämä ominaisuudet vaaditaan tallennuskelpoiselta luokalta:

* Public Sub New() ilman argumentteja (ei toki haittaa jos muitakin on)
* Joko julkiset kentät tai julkiset Read-And-Write-ominaisuudet!

Sen sijaan sillä, laittaako sen <Serializable()> siihen eteen vai ei, ei näytä olevan mitään vaikutusta.

Ja sitten se näkyvyysongelma: Kyllä saman projektin tyypit saa valittua, mutta se täytyy kirjoittaa käsin ja vielä namespacen kanssa, esim. Testiprojekti.EräsLuokka. (Jos haluaa isot kirjaimet niin ne täytyy itse laittaa.) Luokka täytyy olla määritelty Public, Friend ei näytä riittävän.

Toimiikohan tämä homma siistimmin Professional-versiossa?

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta