Define the Plugin In VB.Class - vb.net

I know this is probably a frequently asked question, but I've been spending all day trying to find a solution to this problem. Now, I am working on a project in which VB is partially used. And in a program that has been made by someone else, there is a VB class that I want to develop little a bit by implementing a plugin in it to support dynamically extendable application core.
My question is how to replace "M1065" and "M1064" by using the plugin that I created earlier?
This is the vb class.
Friend Function GetWinderTrouble(ByVal lr As String) As Integer
'左側
If lr = Constant.YARN_WINDER_L Then
Return Me.GetDeviceValue("M1065")
'右側
Else
Return Me.GetDeviceValue("M1064")
End If
End Function
And this is the Plugin that I already created earlier
Imports IPLCComm
Public Class PlugIn
Implements IPLCComm.IPlugIn
Friend Const YARN_WINDER_L As String = "L"
Friend Const GET_WINDERTROUBLE_L As String = "M1065"
Friend Const GET_WINDERTROUBLE_R As String = "M1064"
Public Function GetWinderTrouble(lr As String) As Integer Implements IPlugIn.GetWinderTrouble
If lr = YARN_WINDER_L Then
'Left side
Return Me.GetDeviceValue(GET_WINDERTROUBLE_L)
Else
'Right side
Return Me.GetDeviceValue(GET_WINDERTROUBLE_R)
End If
End Function
End Class

Related

So a VB interface can't have shared functions. Is there an alternative to creating dummy objects?

To avoid getting into the weeds on my particular program, let me just create a simplified case.
I have a generic class that should work on a variety of objects. Each of those objects must implement a certain interface.
What I WANT to say is something like:
Public Interface GenThing
Shared Function thing_name() As String ' This doesn't work! Can't be shared!
Sub FillOne(row As DataRow)
End Interface
public class Thing1
implements GenThing
public shared function thing_name() as string implements GenThing.thing_name
return "thing number one"
end function
public sub FillOne(row as DataRow) implements GenThing.MakeOne
... bunch of work ...
end sub
end class
public class ThingUtil(of T as {GenThing,New})
public function GetList(id as integer) as List(of T)
dim name=T.thing_name() ' This doesn't work!
dim ds as DataSet=GetData(name,id) ' bunch of work here that's the whole point of the class but not relevant to the question
dim my_list = new List(of T)
for each row as DataRow in ds.tables(0).rows
dim my_t = new T()
my_t.FillOne(row)
my_list.add(my_t)
next
return my_list
end function
end class
Do you get my problem? I need every class that implements the interface to have a function that returns a "name" that is used to get the data that is needed to create an instance of the object. But I need to know this name BEFORE I create the instance, because I need it to be able to create the instance. But VB doesn't allow an interface to have a shared function, so what I want to write doesn't work.
So what I've done is this:
I make thing_name not shared.
Then instead of simply "dim name=T.thing_name()", I write
dim dummy = new T()
dim name = dummy.thing_name()
Okay, it works, but it seems really ugly. I create an instance of the object, with all the overhead that that involves, just to get a piece of constant text.
Is there a better way? Or am I making a big deal out of nothing?
Update
I see that two people voted to close this question on the grounds that it is the same as "Why can't we have shared functions in an interface?"
I am not asking why I can't have a shared. I am saying, GIVEN that I can't, how do I solve this particular problem?
There's no really simple way of fixing this, no.
Depending on what thing_name does, however, you might approach things in a different way. If each implementation just returns a constant value, then it's effectively metadata about the class - and could be described in an attribute instead, which can be fetched at execution time. (See Type.GetCustomAttributes.) Unfortunately you can't then enforce all types implementing the interface to be decorated with the attribute - but you could write a unit test to check this pretty easily.
If thing_name needs to really do work at execution time, that's tougher. You could potentially look for a well-known shared method name instead and execute that via reflection (and again have unit tests to check that it's implemented properly).
I realize this is from a few years ago, but running into a similar problem, I wanted to offer a different solution. Pass a delegate as parameter to the ThingUtil constructor. You avoid having to put a shared method in an interface, and the constructor will force you to include the parameter at compile time.
You can add more delegates if needed, or to make it even simpler in this case, just pass name as a string instead of get_name as a delegate.
Define the delegate in the interface:
Public Interface GenThing
Delegate Function ThingNameDelegate() As String
Sub FillOne(row As DataRow)
End Interface
Public Class Thing1
Implements GenThing
Public Shared Function thing_name() As String 'name this whatever you want
Return "thing number one"
End Function
Public Sub FillOne(row As DataRow) Implements GenThing.FillOne
'do stuff
End Sub
End Class
In ThingUtil, add a member to store the delegate, a constructor parameter to to accept, and call it with .Invoke():
Public Class ThingUtil(Of T As {GenThing, New})
Private m_thing_name As GenThing.ThingNameDelegate
Public Sub New(thing_name As GenThing.ThingNameDelegate)
m_thing_name = thing_name
End Sub
Public Function GetList(id As Integer) As List(Of T)
Dim name = m_thing_name.Invoke()
Dim ds As DataSet = GetData(name, id) ' bunch of work here that's the whole point of the class but not relevant to the question
Dim my_list = New List(Of T)
For Each row As DataRow In ds.Tables(0).Rows
Dim my_t = New T()
my_t.FillOne(row)
my_list.Add(my_t)
Next
Return my_list
End Function
End Class
Finally, use it like this:
Dim tu as new ThingUtil(Of Thing1)(AddressOf Thing1.get_name)
tu.GetList(1)

Entity Framework 6 Custom Pluralization in VB.Net

I would like to take advantage of the new ability to customize pluralization with EF6. I've searched the entire intertwangles but can't find a decent example.
I generate my model from the database (SQL Server) and I use custom T4 templates to generate the context and model classes.
From what I can tell, I should be able to create a class which inherits from DbConfiguration and simply place it in the model project. I have done this.
Public Class CustomConfiguration
Inherits DbConfiguration
Public Sub New()
MyBase.New()
SetPluralizationService(New CustomPluralizationService)
End Sub
End Class
This class references CustomPluralizationService which I understand must implement IPluralizationService. Fine and dandy:
Imports System.Data.Entity.Infrastructure.Pluralization
Public Class CustomPluralizationService
Implements IPluralizationService
Public Function Pluralize(word As String) As String Implements System.Data.Entity.Infrastructure.Pluralization.IPluralizationService.Pluralize
End Function
Public Function Singularize(word As String) As String Implements System.Data.Entity.Infrastructure.Pluralization.IPluralizationService.Singularize
End Function
End Class
Of course I should complete the implementation of the Pluralize and Singularize functions, but am at a loss how exactly to do it, as I cannot find a completed example anywhere, in any language. Can someone help, please?
The documentation on MSDN has cryptic garbage like this:
Function Pluralize ( _
word As [%$TOPIC/dn176961_en-us_VS_113_3_0_0_0_0%] _
) As [%$TOPIC/dn176961_en-us_VS_113_3_0_0_0_1%]
Dim instance As [%$TOPIC/dn176961_en-us_VS_113_3_0_1_0_0%]
Dim word As [%$TOPIC/dn176961_en-us_VS_113_3_0_1_0_1%]
Dim returnValue As [%$TOPIC/dn176961_en-us_VS_113_3_0_1_0_2%]
returnValue = instance.Pluralize(word)
[%$TOPIC/dn176961_en-us_VS_113_3_0_2_0_0%] Pluralize(
[%$TOPIC/dn176961_en-us_VS_113_3_0_2_0_1%] word
)
[%$TOPIC/dn176961_en-us_VS_113_3_0_3_0_0%]^ Pluralize(
[%$TOPIC/dn176961_en-us_VS_113_3_0_3_0_1%]^ word
)

VB trouble instantiating object when constructor has a structure data type

I really like the community. I am trying to teach myself vb by trying out what I have learned. I am learning how to use enum's, structures and objects so I thought I would mix them all together ti get a better understanding of whats going on. I am using a Card as an example (been practicing everything with cards)
I created an enum called Suit
Public Enum suit As Integer
Spades = 0
Diamonds =1
Clovers = 2
Hearts = 3
End Enum
Next I created structure that uses the enum data type I just created
Public structure cardValue
Public cardSuit As suit <--- enum
Public cardName As Integer
End Structure
Lastely I created a class of a card
Public Class Card
Private actualCard As cardValue
Get
Return actualCard
End Get
Set(value As cardValue)
End Set
actualCard=value
End Property
Sub New (actualCard As cardValue)
Me.actualCard = actualCard
End Sub
End Class
Now here is my problem
When I goto create a object of the class Card I am not sure how to pass the arguments into the constructor?
Dim myCard As Card = New Card ( I want Spade , and a card value of 10 )
not sure how to pass it a Value, everything I try I get errors of not valid type
I am also not sure how to make the code grey, I am very sorry about that.
With your actual constructor you could do :
Dim c As New Card(New cardValue With {.cardSuit = suit.Spades, .cardName = 10})
But the easiest way would be to change your constructor :
Public Sub New(suitValue As suit, cardValue As Integer)
ActualCard = New cardValue With {.cardSuit = SuitValue, .cardName = CardValue}
End Sub

Writing my first VB.NET Class

I am trying to make 2 variables available throughout my site. I am parsing the URL in order to retreive both of them.
This code on the page itself works fine.
Dim countryLanguage As String
countryLanguage = (Request.ServerVariables("URL"))
Dim langVar = (Mid(countryLanguage, 2, 2))
Dim countryVar = (Mid(countryLanguage, 5, 2))
I have created a class file the code for which is below. With this I get a complilation error (BC30451: Name 'Request' is not declared.).
Public Class url_parser
Public Shared Function urlVars(ByVal langVar, ByVal countryVar) As String
Dim countryLanguage As String
countryLanguage = (Request.ServerVariables("URL"))
Dim langVar = (Mid(countryLanguage, 2, 2))
Dim countryVar = (Mid(countryLanguage, 5, 2))
End Function
End Class
Thanks
System.Web.HttpContext.Current.Request
Your page would already be importing System.Web and already references HttpContext.Current for you internally. In an outside class you have to make sure you import the namespace manually and reference the current context.
On a side note, coupling non-page classes to page lifecycle objects (such as HttpContext) is considered bad design. But for getting started it's fine just to make it work. However, I recommend reading up on the MVC pattern and Separation Of Concerns (and Dependency Injection). If you're a beginner programmer it may be a bit advanced, but if you want to program for a long time consider it a worthy goal to set your sights on :)
You can use System.Web.HttpContext.Current.Request to get the request object for the current thread.
A better way to get your country and language folders is to use Request.Url.Segments.
Public Class url_parser
Public Shared Function urlLanguage() As String
Dim Request = Web.HttpContext.Current.Request
Return Request.Url.Segments(1).TrimEnd("/"c)
End Function
Public Shared Function urlCountry() As String
Dim Request = Web.HttpContext.Current.Request
Return Request.Url.Segments(2).TrimEnd("/"c)
End Function
End Class
Access these static function this way.
Dim MyLanguage = url_parser.urlLanguage
Dim MyCountry = url_parser.urlCountry
In this example, if the Url is "/en/us/" then...
Segment(0) is "/"
Segment(1) is "en/"
Segment(2) is "us/"
The Request object is generally not available within a simple stand-alone class.
I would recommend you pass the string value of countryLanguage as an additional variable from the call within your page class.
If you really must access the Reqeust object from within the class (not recoemmended) use:
HttpContext.Current.Request

VB.NET: How to reference VB.NET module?

I got a Utility module since VB.NET doesn't have static class like C# and Module is the static class in VB.NET. The reason that I use module is because I'm using the Extension method and it can only be use in Module.
I can't reference to this module but if I put my code in a class. I can reference to it without any problem. What could be the reason? I missed C#.
Edit: The module is inside a class library call Utility.
You need to mark the module as Public Module.
I can't reference to this module but if i put my code in a class. I can reference to it without any problem. Does anyone know why?
Because Modules in VB aren't classes and can't be used to instantiate objects. Rather, they're something similar to namespaces, with the difference that namespaces can't contain functions directly. So the reason for modules is to provide a way to group functions logically that don't belong to a class.
This makes a lot of sense when you consider that not everything logically belongs to a class. Consider System.Math. There is absolutely no reason to make that a class, other than a weird OOP purism.
By the way, you can't reference static classes in C# either, at least not if I understand correctly what you mean by “reference”. Perhaps you can clarify this.
.NET compilers can take any type of language syntax and turn it into a .NET equivalent. Sometimes there is a one for one correspondence other times there isn't.
By using the .NET Reflector you can see what the compiler is really doing.
In VB.NET the module exists because of the heritage inherited from Visual BASIC and partly from Microsoft BASIC.
The VB.NET compiler will take this
Public Module CoreModule
Dim R As New System.Random(CInt(Microsoft.VisualBasic.Timer))
Public Function D(ByVal Roll As Integer) As Integer
Return R.Next(0, Roll) + 1
End Function
Public Function _1D6() As Integer
Return D(6)
End Function
Public Function _2D6() As Integer
Return D(6) + D(6)
End Function
Public Function _3D6() As Integer
Return D(6) + D(6) + D(6)
End Function
Public Function _4D6() As Integer
Return D(6) + D(6) + D(6) + D(6)
End Function
Public Function CRLF() As String
Return Microsoft.VisualBasic.ControlChars.CrLf
End Function
End Module
And turn it into this (code left out for brevity)
Public NotInheritable Class CoreModule
' Methods
Shared Sub New()
Public Shared Function _1D6() As Integer
Public Shared Function _2D6() As Integer
Public Shared Function _3D6() As Integer
Public Shared Function _4D6() As Integer
Public Shared Function CRLF() As String
Public Shared Function D(ByVal Roll As Integer) As Integer
' Fields
Private Shared R As Random
End Class
In C# the equivalent is this
public sealed class CoreModule
{
// Fields
private static Random R;
// Methods
static CoreModule();
public static int _1D6();
public static int _2D6();
public static int _3D6();
public static int _4D6();
public static string CRLF();
public static int D(int Roll);
}
All that matter is that the emitted CIL does the job correctly.
This capability is the main reason why so many older Visual BASIC 6 programmers are highly annoyed at MS's changes to the language. For example the keyword Integer emitting a Int32 instead of a Int16.
Modules are exposed to other assemblies referencing the original assembly as long as the module is declared public.
Maybe the methods/subs aren't public? I had that problem once, and it would allow access local code in your class, but not if it was outside your class and marked "Private".
Imports System.Web
Imports System.Web.UI
Module ResponseHelper
<System.Runtime.CompilerServices.Extension()> _
Public Sub Redirect(ByVal response As Net.HttpWebResponse, _
ByVal url As String, ByVal target As String, _
ByVal windowFeatures As String)
If String.IsNullOrEmpty(target) Or _
target.Equals("_self", StringComparison.OrdinalIgnoreCase) And _
String.IsNullOrEmpty(windowFeatures) Then
response.Redirect(url, target, windowFeatures)
Else
Dim page As Page = CType(HttpContext.Current.Handler, Page)
If page Is Nothing Then
Throw New InvalidOperationException("Cannot redirect to new window outside Page context.")
End If
url = page.ResolveClientUrl(url)
Dim script As String
If String.IsNullOrEmpty(windowFeatures) Then
script = "window.open(""{0}"", ""{1}"", ""{2}"";"
Else
script = "window.open(""{0}"", ""{1}"");"
End If
script = String.Format(script, url, target, windowFeatures)
ScriptManager.RegisterStartupScript(page, GetType(Page), "Redirect", script, True)
End If
End Sub
End Module
I don't understand what you are asking.
VB.NET does have static classes, just like in C#, because in VB.NET a Module IS a static class. They are one and the same. Anything you can do with a static class you can do with a Module. Perhaps you haven't marked your Public/Private/Protected access correctly?