VB.NET shared indexer - what am I doing wrong? - vb.net

I have this class:
''' <summary>
''' Utility class for managing ASP.NET session state.
''' </summary>
Public Class SessionHelper
''' <summary>
''' Private constructor to prevent instantiation since classes cannot be declared Shared in VB.
''' </summary>
Private Sub New()
End Sub
''' <summary>
''' Retrieves the current session state.
''' </summary>
''' <returns></returns>
Public Shared ReadOnly Property Session As HttpSessionState
Get
Return HttpContext.Current.Session
End Get
End Property
''' <summary>
''' Retrieves the current system connection string.
''' </summary>
''' <returns></returns>
Public Shared ReadOnly Property ConnectionString As String
Get
Dim raw As String = Session(SessionConstants.DotNetConnectionString)
If raw Is Nothing Then Return Nothing
Return raw.Replace(",", ";")
End Get
End Property
''' <summary>
''' Gets or sets a session variable.
''' </summary>
''' <param name="key">The key of the session variable.</param>
''' <returns>The value of the session variable.</returns>
Public Shared Property Item(ByVal key As String) As Object
Get
Return Session(key)
End Get
Set(value As Object)
Session(key) = value
End Set
End Property
End Class
And I get a compile error when I try to call the shared indexer:
SessionHelper("DotNetConnectionString")
Error BC30109 'SessionHelper' is a class type and cannot be used as an expression.
What am I doing wrong? Or does VB just not support shared indexers? I can call it explicitly as SessionHelper.Item("DotNetConnectionString") but the indexer syntax is not working.

You are accessing the method like a default indexer by leaving out the "Item" method name, but the method is not declared 'Default'. In fact, you can't declare shared indexers in VB.
e.g., you have to change your call to the shared method:
SessionHelper.Item("DotNetConnectionString")
Note: I noticed after posting that Ahmed had included the same information in a comment, so he deserves full credit.

Related

Create Delegate From ComObject Method (via Reflection)

I am able to retrieve it from a COM object via Reflection and run it with the MethodInfo.Invoke method.
However, I am trying to create a Delegate to be faster because I will use it in a loop. Unfortunately, I couldn't find a solution to the error message below. How can I create a delegate for a COM method?
"Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type."
My Delegate:
Public Delegate Function GetDriveNameDelegate(path As String) As String
My test Button:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim fsoType As Type = Type.GetTypeFromProgID("Scripting.FileSystemObject")
Dim fsoInstance As Object = Activator.CreateInstance(fsoType)
'Dim result As Type
#Region " This is working... "
'Dim dispatch As IDispatchInfo = fsoInstance
'dispatch.GetTypeInfo(0, 0, result)
'Dim mi As MethodInfo = result.GetMethod("GetDriveName")
'Dim param = New Object() {"C:\Windows"}
'MessageBox.Show(mi.Invoke(fsoInstance, param))
#End Region
#Region " This is not working... "
Dim fsoDelegate As GetDriveNameDelegate = GetDelegateFromCOM(fsoInstance, "GetDriveName")
MessageBox.Show(fsoDelegate.Invoke("C:\Windows"))
#End Region
End Sub
My Delegate creator function:
Public Function GetDelegateFromCOM(comObj As Object, methodName As String) As GetDriveNameDelegate
Dim result As Type
CType(comObj, IDispatchInfo).GetTypeInfo(0, 0, result)
Dim mi As MethodInfo = result.GetMethod(methodName)
Return [Delegate].CreateDelegate(GetType(GetDriveNameDelegate), mi, True)
End Function
The IDispatch Interface:
<ComImport>
<InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
<Guid("00020400-0000-0000-C000-000000000046")>
Public Interface IDispatchInfo
''' <summary>
''' Gets the number of Types that the object provides (0 or 1).
''' </summary>
''' <param name="typeInfoCount">Returns 0 or 1 for the number of Types provided by <see cref="GetTypeInfo"/>.</param>
''' <remarks>
''' http://msdn.microsoft.com/en-us/library/da876d53-cb8a-465c-a43e-c0eb272e2a12(VS.85)
''' </remarks>
<PreserveSig>
Function GetTypeInfoCount(ByRef typeInfoCount As Integer) As Integer
''' <summary>
''' Gets the Type information for an object if <see cref="GetTypeInfoCount"/> returned 1.
''' </summary>
''' <param name="typeInfoIndex">Must be 0.</param>
''' <param name="lcid">Typically, LOCALE_SYSTEM_DEFAULT (2048).</param>
''' <param name="typeInfo">Returns the object's Type information.</param>
''' <remarks>
''' http://msdn.microsoft.com/en-us/library/cc1ec9aa-6c40-4e70-819c-a7c6dd6b8c99(VS.85)
''' </remarks>
Sub GetTypeInfo(typeInfoIndex As Integer, lcid As Integer, <MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef:=GetType(TypeToTypeInfoMarshaler))> ByRef typeInfo As Type)
''' <summary>
''' Gets the DISPID of the specified member name.
''' </summary>
''' <param name="riid">Must be IID_NULL. Pass a copy of Guid.Empty.</param>
''' <param name="name">The name of the member to look up.</param>
''' <param name="nameCount">Must be 1.</param>
''' <param name="lcid">Typically, LOCALE_SYSTEM_DEFAULT (2048).</param>
''' <param name="dispId">If a member with the requested <paramref name="name"/>
''' is found, this returns its DISPID and the method's return value is 0.
''' If the method returns a non-zero value, then this parameter's output value is
''' undefined.</param>
''' <returns>Zero for success. Non-zero for failure.</returns>
''' <remarks>
''' http://msdn.microsoft.com/en-us/library/6f6cf233-3481-436e-8d6a-51f93bf91619(VS.85)
''' </remarks>
<PreserveSig>
Function GetDispId(ByRef riid As Guid, ByRef name As String, nameCount As Integer, lcid As Integer, ByRef dispId As Integer) As Integer
' NOTE: The real IDispatch also has an Invoke method next, but we don't need it.
' We can invoke methods using .NET's Type.InvokeMember method with the special
' [DISPID=n] syntax for member "names", or we can get a .NET Type using GetTypeInfo
' and invoke methods on that through reflection.
' Type.InvokeMember: http://msdn.microsoft.com/en-us/library/de3dhzwy.aspx
End Interface

Is it impossible to overload a generic method in VB.NET by changing only the type constraint and the return type?

I have these two nearly identical methods:
''' <summary>
''' Converts a <see cref="DBNull"/> to an actual Nothing value.
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="val"></param>
''' <returns></returns>
Public Shared Function DBNullToNull(Of T As Structure)(ByVal val As Object) As T?
If TypeOf val Is DBNull Then Return Nothing Else Return Val
End Function
''' <summary>
''' Converts a <see cref="DBNull"/> to an actual Nothing value.
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="val"></param>
''' <returns></returns>
Public Shared Function DBNullToNull(Of T As Class)(ByVal val As Object) As T
If TypeOf val Is DBNull Then Return Nothing Else Return Val
End Function
But I get this compile error:
Public Shared Function DBNullToNull(Of T As Structure)(val As Object) As T?' and 'Public Shared Function DBNullToNull(Of T As Class)(val As Object) As T' cannot overload each other because they differ only by return types.
But they differ not only by return types, but also by generic type constraints (one works on structures, the other on classes) which are mutually exclusive. Is this still not allowed?
Of course I can rename them so they don't conflict, but that would be a bit annoying! Is there any other way to do this?

Adding Attribute to property in vb.net

I'm trying to add an attribute to a property in VB.NET, so I can then check that attribute later
I'm not sure if I'm going about this the correct way. Some pointers on how to do this and also then how to check that attribute at run time would be great.
Public Class Person
''' <summary>
''' This is forename property
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
<ExcludeFromModifiedComparision(True)>
Public Property Forename = "Mickey"
<ExcludeFromModifiedComparision(False)>
Public Property Surname = "Mouse"
End Class
Public Class ExcludeFromModifiedComparisionAttribute
Inherits Attribute
Public Sub New(ByVal value As Boolean)
' Not sure what to do here?
Throw New NotImplementedException()
End Sub
End Class

my.settings and descriptions? And getting them into a propertygrid?

I recently learned of the propertygrid object usage with the my.settings object for a project. I like this very much and I was wondering if there is a way to include descriptions with my settings so that they will be included in the propertygrid in the lower description panel?
I found a couple of old (2003) codeproj articles that covers this but it requires a lot of custom work and was hoping that there has been an easier method to come around.
This is very simple to do and doesn't require any custom classes. Just open Settings.Designer.cs in Settings.settings in Propertiesin your Solution Explorer. For every property you can add a description readable by PropertyGrid by adding:
[Description("Your custom description here")]
The same can be done with:
[Category("Your custom category here")]
These require using System.ComponentModel;.
Your descriptions will show up exactly as expected in your PropertyGrid with no other work required.
NOTE: If the file is regenerated your changes will probably be lost, so that is just something to be mindful if you plan on editing through the auto-generate tool.
You could wrap the settings in a simple class with properties for each setting you have in your application that simply gets/sets the setting value and attach the [Description("Some descr")] attribute to each property in that wrapper class to show the descriptions in the PropertyGrid.
DTools includes a pair of classes that make it easier to maintain your proxy settings object. It defines description and default attributes that work with the PropertyGrid and get their value by looking up the corresponding attribute in the settings property. This allows you to maintain description and default value using the Settings Designer without having to remember to update those attributes manually in your proxy settings object.
''' <summary><see cref="DescriptionAttribute"/> that takes its value from <see cref="System.Configuration.SettingsDescriptionAttribute"/></summary>
''' <author www="http://dzonny.cz">Đonny</author>
''' <version version="1.5.2" stage="RC"><see cref="VersionAttribute"/> and <see cref="AuthorAttribute"/> removed</version>
Public Class SettingsInheritDescriptionAttribute : Inherits DescriptionAttribute
''' <summary>CTor</summary>
''' <param name="Settings">The data type that contains property with name specified in <paramref name="Property"/></param>
''' <param name="Property">Name of the property which's <see cref="SettingsDescriptionAttribute"/> initializes this attribute</param>
''' <param name="AlternateDescription">Alternative description used in case of failure of getting description form specified property</param>
Public Sub New(ByVal Settings As Type, ByVal [Property] As String, Optional ByVal AlternateDescription As String = "")
'#If VBC_VER >= 9 Then
MyBase.New(If(AlternateDescription = "", [Property], AlternateDescription))
'#Else
' MyBase.New(iif(AlternateDescription = "", [Property], AlternateDescription))
'#End If
Me.Settings = Settings
Me.Property = [Property]
End Sub
''' <summary>The data type that contains property with name spacified in <see cref="[Property]"/></summary>
Private Settings As Type
''' <summary>Name of the property which's <see cref="SettingsDescriptionAttribute"/> initializes this attribute</summary>
Private [Property] As String
''' <summary>Gets or sets the string stored as the description.</summary>
''' <returns>The string stored as the description. The default value is an empty string ("").</returns>
Public Overrides ReadOnly Property Description() As String
Get
Dim sds As Object() = Settings.GetProperty([Property]).GetCustomAttributes(GetType(SettingsDescriptionAttribute), True)
If sds IsNot Nothing AndAlso sds.Length > 0 Then
Return CType(sds(0), SettingsDescriptionAttribute).Description
Else
Return MyBase.DescriptionValue
End If
End Get
End Property
End Class
''' <summary><see cref="DefaultValueAttribute"/> that takes its value from <see cref="System.Configuration.DefaultSettingValueAttribute"/></summary>
''' <author www="http://dzonny.cz">Đonny</author>
''' <version version="1.5.2" stage="RC"><see cref="VersionAttribute"/> and <see cref="AuthorAttribute"/> removed</version>
Public Class SettingsInheritDefaultValueAttribute : Inherits DefaultValueAttribute
''' <summary>CTor</summary>
''' <param name="Settings">The data type that contains property with name defined in <paramref name="Property"/></param>
''' <param name="Property">Name of property from which's <see cref="DefaultSettingValueAttribute"/> this attribute is initialized</param>
''' <param name="Type">The data type of the value</param>
''' <param name="AlternateDefaultValue">Alternative default value used when fetching fails</param>
Public Sub New(ByVal Settings As Type, ByVal [Property] As String, ByVal Type As Type, Optional ByVal AlternateDefaultValue As String = "")
MyBase.New(Type, AlternateDefaultValue)
Me.Settings = Settings
Me.Property = [Property]
Me.ValueType = Type
End Sub
''' <summary>CTor for default values of <see cref="String"/> type</summary>
''' <param name="Settings">The data type that contains property with name defined in <paramref name="Property"/></param>
''' <param name="Property">Name of property from which's <see cref="DefaultSettingValueAttribute"/> this attribute is initialized</param>
Public Sub New(ByVal Settings As Type, ByVal [Property] As String)
Me.New(Settings, [Property], GetType(String))
End Sub
''' <summary>Contains value of the <see cref="Settings"/> property</summary>
<EditorBrowsable(EditorBrowsableState.Never)> Private _Settings As Type
''' <summary>Contains value of the <see cref="[Property]"/> property</summary>
<EditorBrowsable(EditorBrowsableState.Never)> Private [_Property] As String
''' <summary>Contains value of the <see cref="ValueType"/> property</summary>
<EditorBrowsable(EditorBrowsableState.Never)> Private _ValueType As Type
''' <summary>Gets the default value of the property this attribute is bound to.</summary>
''' <returns>An <see cref="System.Object"/> that represents the default value of the property this attribute is bound to.</returns>
''' <remarks>Default values can be obtained if stored in form that can be directly returned or if stored as XML-serialized values.</remarks>
Public Overrides ReadOnly Property Value() As Object
Get
Dim sds As Object() = Settings.GetProperty([Property]).GetCustomAttributes(GetType(DefaultSettingValueAttribute), True)
If sds IsNot Nothing AndAlso sds.Length > 0 Then
Try
Dim mySerializer As Xml.Serialization.XmlSerializer = New Xml.Serialization.XmlSerializer(ValueType)
Dim stream As New System.IO.StringReader(CType(sds(0), DefaultSettingValueAttribute).Value)
Return mySerializer.Deserialize(stream)
Catch
Dim a As New DefaultValueAttribute(ValueType, CType(sds(0), DefaultSettingValueAttribute).Value)
Return a.Value
End Try
Else
Return MyBase.Value
End If
End Get
End Property
''' <summary>The data type that contains property with name defined in <see cref="[Property]"/></summary>
Public Property Settings() As Type
Get
Return _Settings
End Get
Protected Set(ByVal value As Type)
_Settings = value
End Set
End Property
''' <summary>Name of property from which's <see cref="DefaultSettingValueAttribute"/> this attribute is initialized</summary>
Public Property [Property]() As String
Get
Return [_Property]
End Get
Protected Set(ByVal value As String)
[_Property] = value
End Set
End Property
''' <summary>The data type of the value</summary>
Public Property ValueType() As Type
Get
Return _ValueType
End Get
Protected Set(ByVal value As Type)
_ValueType = value
End Set
End Property
End Class
Use it like this:
Public Class ProxySettings
''' <summary>Wraps <see cref="My.MySettings.SomeSetting"/> property</summary>
<SettingsInheritDescription(GetType(My.MySettings), "SomeSetting")> _
<SettingsInheritDefaultValue(GetType(My.MySettings), "SomeSetting")> _
Public Property SomeSetting() As Decimal
Get
Return My.Settings.SomeSetting
End Get
Set(ByVal value As Decimal)
My.Settings.SomeSetting = value
End Set
End Property
End Class

Inherited Public Properties not showing up in Intellisense

I have inherited a class in vb.net and when I create the object, I am only seeing one of the inherited public properties in intellisense. Any solution to this problem?
print("Public Class CompanyMailMessage
Inherits MailMessage
Private AdobeDisclaimer As String = "You will need Adobe Acrobat to read this file. If it is not installed on your computer go to http://www.adobe.com/support/downloads/main.html to download. Thank You"
Private _Body As String
Private _IncludeAdobeDisclaimer As Boolean = False
''' <summary>
''' Gets or sets the body of the message
''' </summary>
''' <returns>A System.String that contains the body content.</returns>
Public Property Body() As String
Get
If _IncludeAdobeDisclaimer Then
_Body = _Body + AdobeDisclaimer
End If
Return _Body
End Get
Set(ByVal value As String)
_Body = value
End Set
End Property
''' <summary>
''' Gets or sets a value that determines if a message that states that Adobe Acrobat must be used to open the attached files is included in the body of the message
''' </summary>
''' <value></value>
''' <returns>True if ;otherwise, false</returns>
''' <remarks></remarks>
Public Property IncludeAdobeDisclaimer() As Boolean
Get
Return _IncludeAdobeDisclaimer
End Get
Set(ByVal value As Boolean)
_IncludeAdobeDisclaimer = value
End Set
End Property
''' <summary>
''' Initializes an instance of the CompanyMailMessageclass
''' </summary>
''' <remarks></remarks>
Public Sub New()
End Sub
''' <summary>
''' Initializes an instance of the CompanyMailMessageclass with plain text in the body
''' </summary>
''' <param name="from">The email address of the sender</param>
''' <param name="fromName">The name of the sender</param>
''' <param name="to"></param>
''' <param name="subject"></param>
''' <param name="body"></param>
''' <remarks></remarks>
Public Sub New(from as String,fromName As String,[to] as String,subject As String,body As String)
MyBase.FromAddress = New EmailAddress(from,fromName)
MyBase.ToAddresses.Add([to])
MyBase.Subject = subject
_Body = body
MyBase.Items.Add(New MessageContent(MimeType.MessageRfc822,body))
End Sub");
I would suggest opening Reflector and opening the 3rd party dll. I'm guessing the properties will be internal (friend in vb.net, I think) and that's the reason.