I'm using a class that Implements from an interface.
I want to implement a property from the interface but I'm getting error:
Class 'ListManager' must implement 'Property Count As Integer' for interface 'IListManager(Of T)'. Implementing property must have matching 'ReadOnly' or 'WriteOnly' specifiers.
Interface:
Namespace Assign_1
Public Interface IListManager(Of T)
''' <summary>
''' Return the number of items in the collection m_list
''' </summary>
Property Count As Integer
End Namespace
Class:
Namespace Assign_1
Public Class ListManager(Of T)
Implements IListManager(Of T)
Protected m_list As List(Of T)
''' <summary>
''' Constructor
''' </summary>
Public Sub New()
MyBase.New()
m_list = New List(Of T)
End Sub
''' <summary>
''' Property to count the list
''' </summary>
Public ReadOnly Property Count As Integer
Get
Return m_list.Count
End Get
End Property
End Namespace
Does anyone know the problem?
It shouldn't be necessary to define the Interface as a generic since an interface just establishes a contract of which properties and methods are implemented.
Public Interface IListManager
ReadOnly Property Count As Int32
' function version
Function GetCount() As Integer
End Interface
Public Class ListMgr(Of T)
Implements IListManager
Private myList As List(Of T)
Public ReadOnly Property Count As Integer Implements IListManager.Count
Get
Return myList.Count
End Get
End Property
Public Function GetCount() As Integer Implements IListManager.GetCount
Return myList.Count
End Function
End Class
If you did need the interface to be generic there is just a small change:
Public ReadOnly Property Count As Integer Implements IListManager(Of T).Count
After you type in Implements IMyInterface VS will add the boilerplate property and method code when you press enter.
This works for me
Public Interface IListManager(Of T)
ReadOnly Property count As Integer
End Interface
Public Class ListManager(Of T) : Implements IListManager(Of TabAlignment)
Protected m_list As List(Of T)
''' <summary>
''' Constructor
''' </summary>
Public Sub New()
MyBase.New()
m_list = New List(Of T)
End Sub
Public ReadOnly Property count As Integer Implements IListManager(Of TabAlignment).count
Get
Return Me.m_list.Count
End Get
End Property
End Class
Related
I created a class that inherits button in win forms
How can i create a Browsable property with type dictionary ?
here is my code
but i didn't find it in properties menu
vb.net
<Browsable(True)>
Property Set_ddn() As Dictionary(Of TextBox, String)
Get
Return ddn
End Get
Set(ByVal value As Dictionary(Of TextBox, String))
ddn = value
End Set
End Property
how can i make it browsable ?
or what should i use instead of dictionary?
or another solution
i found the answer here (C#)
https://stackoverflow.com/a/42829336/1543991
rewrite code for vb.net
You should write your own type descriptor by deriving from CustomTypeDescriptor or implementing ICustomTypeDescriptor. Here is an example:
MyPropertyDescriptor
Provide a custom description for a property. Here I override Attributes property to provide a new list of attributes for property. For example I check if the property has [Category("Extra")], I also added a [Browsable(false)] to its attribute collection.
Imports System
Imports System.ComponentModel
Imports System.Linq
Public Class MyPropertyDescriptor
Inherits PropertyDescriptor
Private o As PropertyDescriptor
Public Sub New(ByVal originalProperty As PropertyDescriptor)
MyBase.New(originalProperty)
o = originalProperty
End Sub
Public Overrides Function CanResetValue(ByVal component As Object) As Boolean
Return o.CanResetValue(component)
End Function
Public Overrides Function GetValue(ByVal component As Object) As Object
Return o.GetValue(component)
End Function
Public Overrides Sub ResetValue(ByVal component As Object)
o.ResetValue(component)
End Sub
Public Overrides Sub SetValue(ByVal component As Object, ByVal value As Object)
o.SetValue(component, value)
End Sub
Public Overrides Function ShouldSerializeValue(ByVal component As Object) As Boolean
Return o.ShouldSerializeValue(component)
End Function
Public Overrides ReadOnly Property Attributes As AttributeCollection
Get
Dim attributes = MyBase.Attributes.Cast(Of Attribute)().ToList()
Dim category = attributes.OfType(Of CategoryAttribute)().FirstOrDefault()
If category IsNot Nothing AndAlso category.Category = "Extra" Then attributes.Add(New BrowsableAttribute(False))
Return New AttributeCollection(attributes.ToArray())
End Get
End Property
Public Overrides ReadOnly Property ComponentType As Type
Get
Return o.ComponentType
End Get
End Property
Public Overrides ReadOnly Property IsReadOnly As Boolean
Get
Return o.IsReadOnly
End Get
End Property
Public Overrides ReadOnly Property PropertyType As Type
Get
Return o.PropertyType
End Get
End Property
End Class
MyTypeDescriptor
Used to provide a list of custom property descriptors for a type.
Imports System
Imports System.ComponentModel
Imports System.Linq
Public Class MyTypeDescriptor
Inherits CustomTypeDescriptor
Private original As ICustomTypeDescriptor
Public Sub New(ByVal originalDescriptor As ICustomTypeDescriptor)
MyBase.New(originalDescriptor)
original = originalDescriptor
End Sub
Public Overrides Function GetProperties() As PropertyDescriptorCollection
Return Me.GetProperties(New Attribute() {})
End Function
Public Overrides Function GetProperties(ByVal attributes As Attribute()) As PropertyDescriptorCollection
Dim properties = MyBase.GetProperties(attributes).Cast(Of PropertyDescriptor)().[Select](Function(p) New MyPropertyDescriptor(p)).ToArray()
Return New PropertyDescriptorCollection(properties)
End Function
End Class
MyTypeDescriptionProvider
Used to connect MyTypeDescriptor to a class using TypeDescriptionProvider attribute.
Imports System
Imports System.ComponentModel
Public Class MyTypeDescriptionProvider
Inherits TypeDescriptionProvider
Public Sub New()
MyBase.New(TypeDescriptor.GetProvider(GetType(Object)))
End Sub
Public Overrides Function GetTypeDescriptor(ByVal type As Type, ByVal o As Object) As ICustomTypeDescriptor
Dim baseDescriptor As ICustomTypeDescriptor = MyBase.GetTypeDescriptor(type, o)
Return New MyTypeDescriptor(baseDescriptor)
End Function
End Class
MySampleClass
Contains a property decorated with [Category("Extra")]. So Property2 will not be visible in property grid. (In visual studio or collection editor or even run-time property grid)
<TypeDescriptionProvider(GetType(MyTypeDescriptionProvider))>
Public Class MySampleClass
Public Property Property1 As Integer
<Category("Extra")>
Public Property Property2 As String
End Class
MyComplexComponent
Contains a collection of MySampleClass. So you can see behavior of MySampleClass in collection editor.
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Public Class MyComplexComponent
Inherits Component
Public Sub New()
MySampleClasses = New Collection(Of MySampleClass)()
End Sub
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
Public Property MySampleClasses As Collection(Of MySampleClass)
End Class
I was analyzing a code. There we have a base class (not abstract) implementing an interface. Then we have a derived class of the base class which also implements the interface.
Interface:
Public Interface MainInterface
Function getMetaThreads(ByVal ThreadCount As Integer) As String()
Property Name() As String
Property TargetDirectory() As String
Property TimeOut() As Long
ReadOnly Property ExecutableAssembly() As String
ReadOnly Property IsVersionValid() As Boolean
End Interface
Base class:
Public Class BaseClass
Implements MainInterface
Public Sub print()
Console.WriteLine("BaseClass printing")
End Sub
Public ReadOnly Property ExecutableAssembly As String Implements MainInterface.ExecutableAssembly
...
End Property
Public ReadOnly Property IsVersionValid As Boolean Implements MainInterface.IsVersionValid
...
End Property
Protected strName As String = ""
Protected strTargetDirectory As String = ""
Protected lngTimeout As Long = 0
Public Property Name As String Implements MainInterface.Name
...
End Property
Public Property TargetDirectory As String Implements MainInterface.TargetDirectory
...
End Property
Public Property TimeOut As Long Implements MainInterface.TimeOut
...
End Property
Public Function getMetaThreads(ThreadCount As Integer) As String() Implements MainInterface.getMetaThreads
...
End Function
Public Overridable Function myOwnFunc() As String
Return ""
End Function
End Class
Derived Class:
Public Class SubClass
Inherits BaseClass
Implements MainInterface
Public Function getMetaThreads(ThreadCount As Integer) As String() Implements MainInterface.getMetaThreads
Return myOwnFunc()
End Function
Overrides Function myOwnFunc() As String()
Dim l As New List (Of String)
l.Add("44")
l.Add("33")
return l.ToArray()
End Function
End Class
Does it make sense to implement the interface in the derived class again? Is there a reason or a case where this becomes necessary? I think that having the base class implement the interface should be enough and implementing it in the interface is redundant.
I have custom attribute applied to CRUD repository methods to control access:
Public Class SecureDbContextGenericRepository(Of TEntity As Class, TContext As DbContext)
Inherits DbContextGenericRepository(Of TEntity, TContext)
Public Sub New(connectionService As IConnectionService)
MyBase.New(connectionService)
End Sub
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
Public Overrides Sub Delete(ParamArray entities() As TEntity)
MyBase.Delete(entities)
End Sub
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
Public Overrides Sub Insert(ParamArray entities() As TEntity)
MyBase.Insert(entities)
End Sub
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataReader)>
Public Overrides Function [Select](Optional predicate As Func(Of TEntity, Boolean) = Nothing) As IList(Of TEntity)
Return MyBase.Select(predicate)
End Function
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
Public Overrides Sub Update(ParamArray entities() As TEntity)
MyBase.Update(entities)
End Sub
End Class
This is implementation of attribute:
Public Class EmployeeRoleRequirementAttribute
Inherits CodeAccessSecurityAttribute
Public Sub New(action As SecurityAction)
MyBase.New(action)
End Sub
Public Overrides Function CreatePermission() As IPermission
Return New EmployeeRolePermission(_EmployeeRoles)
End Function
Public Property EmployeeRoles As EmployeeRoles
End Class
<Flags>
Public Enum EmployeeRoles As Integer
DataReader = 0
DataWriter = 1
End Enum
And permission:
Public Class EmployeeRolePermission
Implements IPermission
Public Sub New(employeeRoles As EmployeeRoles)
_EmployeeRoles = employeeRoles
End Sub
Public Function Copy() As IPermission Implements IPermission.Copy
Return New EmployeeRolePermission(_EmployeeRoles)
End Function
Public Sub Demand() Implements IPermission.Demand
Dim principal = DirectCast(Thread.CurrentPrincipal, ProductionAssistantPrincipal)
If Not principal.IsInRole(_EmployeeRoles) Then
Throw New SecurityException(String.Format(My.Resources.EmployeeRoleNotFound,
principal.Identity.Name,
_EmployeeRoles.ToString()))
End If
End Sub
Public Sub FromXml(e As SecurityElement) Implements ISecurityEncodable.FromXml
Throw New NotImplementedException()
End Sub
Public Function Intersect(target As IPermission) As IPermission Implements IPermission.Intersect
Return New EmployeeRolePermission(_EmployeeRoles And DirectCast(target, EmployeeRolePermission).EmployeeRoles)
End Function
Public Function IsSubsetOf(target As IPermission) As Boolean Implements IPermission.IsSubsetOf
Return _EmployeeRoles.HasFlag(DirectCast(target, EmployeeRolePermission).EmployeeRoles)
End Function
Public Function ToXml() As SecurityElement Implements ISecurityEncodable.ToXml
Throw New NotImplementedException()
End Function
Public Function Union(target As IPermission) As IPermission Implements IPermission.Union
Return New EmployeeRolePermission(_EmployeeRoles Or DirectCast(target, EmployeeRolePermission).EmployeeRoles)
End Function
Public ReadOnly Property EmployeeRoles As EmployeeRoles
End Class
Every time one of the CRUD methods are reached, TypeLoadException is thrown. I really dont know cause of this, but if I remove attributes from CRUD methods, everything works fine.
This seems to be due to the enum-valued property on the attribute (see https://connect.microsoft.com/VisualStudio/feedback/details/596251/custom-cas-attributes-with-an-enum-property-set-cause-a-typeloadexception for details). To work around this issue, you could use a string-valued property on the attribute and cast to an enum either in the property setter or just before creating the permission. (Personally, I'd probably opt for the former in the interests of enabling early validation, but ymmv...)
Another workaround is making attribute property of type, which is used in Enum, in this case Integer.
Public Class EmployeeRoleRequirementAttribute
Inherits CodeAccessSecurityAttribute
Public Sub New(action As SecurityAction)
MyBase.New(action)
End Sub
Public Overrides Function CreatePermission() As IPermission
Return New EmployeeRolePermission(CType(_RequiredEmployeeRoles, EmployeeRoles))
End Function
Public Property RequiredEmployeeRoles As Integer
End Class
<Flags>
Public Enum EmployeeRoles As Integer
DataReader = 0
DataWriter = 1
End Enum
Then you dont need to use String, which does not allow easy combining of flags when attribute is used:
<EmployeeRoleRequirement(SecurityAction.Demand, RequiredEmployeeRoles:=EmployeeRoles.DataReader Or EmployeeRoles.DataWriter)>
Sub SecuredMethod()
End Sub
Outside the class I'd like to be able to access CCTV.Camera.Brightness property as ReadOnly, but methods within the CCTV class should be able to modify the Brightness property. Please can you advise on how to achieve this?
I think I need to add an Interface that exposes some properties and hides others, but I'm not sure of the implementation. [Note the constructor and main sub are obviously contrived for this example and testing].
Public Class CCTV
Public Class Camera
Public Property Name as String
Public Property Brightness as Integer
End Class
Dim cameras as New Dictionary(Of String, Camera)
Public Sub New()
Dim cam As New Camera
cam.Name = "driveway"
cam.Brightness = 5
cameras.Add(cam.Name, cam)
End Sub
Public Sub ChangeBrightness(value as Integer)
cameras("driveway").Brightness = value
End Sub
End Class
Sub main()
Dim MyCCTV = new CCTV
MyCCTV.ChangeBrightness(10)
if MyCCTV("driveway").Brightness = 10 then Console.Write("Brightness is 10")
End Sub
Get getter and the setter of a property can have different accessibility modifiers. In this case you want Brightness to be readable by everybody but only the code you trust should be able to write it. You do so like this:
Public Class Camera
Private _brightness As Integer
Public Property Brightness As Integer
Get
Return _brightness
End Get
Friend Set(value As Integer)
_brightness = Value
End Set
End Property
'' etc...
End Class
Note the added Friend keyword, it limits access to the code in the same project that Camera class is a part of. It can also be Private or Protected if you want to limit access to only code inside the Camera class or its derived classes.
no interface is need in this case.You simply have to create your property as readonly.when you set the property as readonly assume that the value will stored within a private variable and at that point should be better pass it or to a method or to the subnew using overloads methods let me show you an example:
Public Class CCTV
Public Class Camera
Private _Name As String
Public Property Name() As String
Get
Return _Name
End Get
Set(ByVal value As String)
_Name = value
End Set
End Property
Private _Brightness As String
Public ReadOnly Property Brightness() As String
Get
Return _Brightness
End Get
End Property
''' <summary>
''' Defautl sub new method
''' </summary>
''' <remarks></remarks>
Sub New()
End Sub
''' <summary>
''' second overload
''' </summary>
''' <param name="cameraName"></param>
''' <param name="brightness"></param>
''' <remarks></remarks>
Sub New(ByVal cameraName As String, ByVal brightness As Integer)
Me.Name = cameraName
Me._Brightness = brightness
End Sub
''' <summary>
''' Change brigthness
''' </summary>
''' <param name="value"></param>
''' <remarks></remarks>
Public Sub setUpCameraBrightness(ByVal value As Integer)
'take care to use private varibale so it will reflcet changes into propetry readonly
Me._Brightness = value
End Sub
End Class
Dim cameras As New Dictionary(Of String, Camera)
Public Sub New()
'two differnet approach
'first overaload:
Dim cam As New Camera()
cam.Name = "yourcamname"
cam.setUpCameraBrightness(10)
cameras.Add(cam.Name, cam)
''second approch declarative value:
Dim cam2 As New Camera("yourcamname", 10)
cameras.Add(cam2.Name, cam2)
End Sub
Public Sub ChangeBrightness(value As Integer)
cameras("driveway").setUpCameraBrightness(100)
End Sub
End Class
Sub main()
Dim MyCCTV = New CCTV
MyCCTV.ChangeBrightness(10)
If MyCCTV("driveway").Brightness = 10 Then Console.Write("Brightness is 10")
End Sub
If have got the following definitions of constants:
Protected Const Xsl As String = "Configuration.Xsl"
Protected Const Form As String = "Settings.Form"
Protected Const Ascx As String = "Implementation.Ascx"
...
To fill a dictionary I use this constants as keys:
MyDictionary.Add(Converter.Xsl, "Item 1")
MyDictionary.Add(Converter.Form, "Item 2")
MyDictionary.Add(Converter.Ascx, "Item 3")
...
Now I run throug a loop of XML files and extract the name of the root node:
Dim document As New XmlDocument
document.Load(File.FullName)
Dim rootName As String = document.DocumentElement.Name
The root name matchs with the name of the constant. To get the value of an item from the dictionary I can use something like this:
Select Case rootName.ToUpper
Case "Xsl".ToUpper
DictionaryValue = MyDictionary(Class.Xsl)
Case "Form".ToUpper
DictionaryValue = MyDictionary(Class.Form)
Case "Ascx".ToUpper
DictionaryValue = MyDictionary(Class.Ascx)
...
Case Else
End Select
If a constant is added or removed I also have to change the selection. Is there another way to get the value of a constant? Something like
DictionaryValue = MyDictionary(SomeFunctionToGetConstantValue(rootName))
Thanks for any response.
Try this:
For Each sKey As String In MyDictionary.Keys
If rootName.Equals(sKey, StringComparison.CurrentCultureIgnoreCase) Then
DictionaryValue = MyDictionary(sKey)
Exit For
End If
Next
At least it will reduce the amount of coding in the select case.
#Clara Onager
My solution I used was the following
Me.GetType.GetField(
"Xsl",
Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Static Or System.Reflection.BindingFlags.FlattenHierarchy
).GetValue(Nothing)
This is a bit of a whopper but I think it provides a pretty elegant solution overall. This is how it is used:
Public Class ConstantsExample
Public Sub UseConstant()
Dim value As String = Constants.Types(TypeA)
Dim category As String = Constants.Categories(General)
End Sub
End Class
As you can see the code where you use it is as short as it can be made. It does rely on a big pile of source code though:
Public Enum TypeCodes
<Description("Type A")> TypeA = 0
<Description("Type B")> TypeB
<Description("Type C")> TypeC
End Enum
Public Enum CategoryCodes
<Description("General")> General = 0
<Description("Specific")> Specific
<Description("Other")> Other
End Enum
Public NotInheritable Class Constants
#Region "Resources"
Private Shared myTypes As Dictionary(Of TypeCodes, ConstantItem) = Nothing
Public Shared ReadOnly Property Types() As Dictionary(Of TypeCodes, ConstantItem)
Get
If myTypes Is Nothing Then
myTypes = New Dictionary(Of TypeCodes, ConstantItem)
BuildTypes(myTypes)
End If
Return myTypes
End Get
End Property
Private Shared Sub BuildTypes(ByRef dict As Dictionary(Of TypeCodes, ConstantItem))
With dict
.Add(TypeCodes.TypeA, New ConstantItem(TypeCodes.TypeA.Description, "Type A are..."))
.Add(TypeCodes.TypeB, New ConstantItem(TypeCodes.TypeB.Description, "Type B are..."))
.Add(TypeCodes.TypeC, New ConstantItem(TypeCodes.TypeC.Description, "Type C are..."))
End With
End Sub
#End Region
#Region "Categories"
Private Shared myCategories As Dictionary(Of CategoryCodes, ConstantItem) = Nothing
Public Shared ReadOnly Property Categories() As Dictionary(Of CategoryCodes, ConstantItem)
Get
If myCategories Is Nothing Then
myCategories = New Dictionary(Of CategoryCodes, ConstantItem)
BuildCategories(myCategories)
End If
Return myCategories
End Get
End Property
Private Shared Sub BuildCategories(ByRef dict As Dictionary(Of CategoryCodes, ConstantItem))
With dict
.Add(CategoryCodes.General, New ConstantItem(CategoryCodes.General.Description, "General category"))
.Add(CategoryCodes.Specific, New ConstantItem(CategoryCodes.Specific.Description, "Specific category"))
.Add(CategoryCodes.Other, New ConstantItem(CategoryCodes.Other.Description, "Other category"))
End With
End Sub
#End Region
End Class
Public NotInheritable Class ConstantItem
#Region "Constructors"
''' <summary>
''' Default constructor.
''' </summary>
Public Sub New()
'Do nothing
End Sub
''' <summary>
''' Simple constructor.
''' </summary>
Sub New(value As String)
Me.Name = value
Me.Description = value
End Sub
''' <summary>
''' Proper constructor.
''' </summary>
Sub New(name As String, description As String)
Me.Name = name
Me.Description = description
End Sub
#End Region
Property Name As String
Property Description As String
''' <summary>
''' See http://stackoverflow.com/questions/293215/default-properties-in-vb-net
''' </summary>
Public Shared Widening Operator CType(value As String) As ConstantItem
Return New ConstantItem(value)
End Operator
''' <summary>
''' See http://stackoverflow.com/questions/293215/default-properties-in-vb-net
''' </summary>
Public Shared Widening Operator CType(value As ConstantItem) As String
Return value.Name
End Operator
End Class
Note the use of the Widening Operator to dispense with having to type .Item. If you'd rather not use the Widening Operator then simple comment that bit out and change Constants.Types(TypeA) to Constants.Types.Item(TypeA).
This is the Description Extension you may need:
Public Module Extensions
Private Enum SampleDescription
<Description("Item One")> ItemOne = 1
<Description("Item Two")> ItemTwo = 2
<Description("Item Three has a long description")> ItemThree = 3
End Enum
''' <summary>
''' This procedure gets the description attribute of an enum constant, if any. Otherwise it gets
''' the string name of the enum member.
''' </summary>
''' <param name="value"></param>
''' <returns></returns>
''' <remarks>Usage: myenum.Member.Description()
''' Add the Description attribute to each member of the enumeration.</remarks>
<Extension()> _
Public Function Description(ByVal value As [Enum]) As String
Dim fi As Reflection.FieldInfo = value.GetType().GetField(value.ToString())
Dim aattr() As DescriptionAttribute = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())
If aattr.Length > 0 Then
Return aattr(0).Description
Else
Return value.ToString()
End If
End Function
End Module
And these are the Imports statements I used (the Assembly is called MyPatterns):
Imports System.ComponentModel
Imports MyPatterns.TypeCodes
Imports MyPatterns.CategoryCodes
Importing the two 'codes' allows you to do without the prefix for the Enum which shortens the code.