I am working on a C#.net. I have a code of vb.net and I want to convert those code into C#.
I have done all my task but while running application it gives me a error of object not set to an object reference. below is my VB.net code. I have used third party ddl in my code so ExchangeList is a class of that dll.
Private WithEvents moExchanges As ExchangeList
Private Sub RequestChartData()
Trace.WriteLine("Init")
moExchanges = moHost.MarketData.Exchanges
End Sub
Now below is my C#.code
Private Host moHost;
Private ExchangeList moExchanges;
private void RequestChartData()
{
Trace.WriteLine("Init");
moExchanges = moHost.MarketData.Exchanges;
}
Thanks.
It's not possible to tell you with 100% certainty the source of your object not set to an object reference. without seeing more code, but the error appears to be telling you that moHost is null - in other words, you haven't created an instance of the object yet.
So when you try to call MarketData.Exchanges on the object (so you can assign it to moExchanges, it's throwing the error.
Find moHost in your code and make sure you have that you have assigned an instance of that object to it (by calling it's constructor, like moHost = new Host() or whatever the constructor is), and this should fix your error.
UPDATE
You never initialize moHost. This line:
private Host moHost;
Simply declares the object - at this point it's null. So when you try to access any instance methods/properties, you get the object not set to an object reference error.
You need to create an instance of moHost by calling it's constructor, something like this:
private Host moHost = new Host();
The constructor may require parameters - take a look at the documentation for the third-party DLL (intellisense in the IDE may also tell you what parameters, if any, are needed).
This will take care of your error.
()Instead of:
Private Host moHost;
Private ExchangeList moExchanges;
I think you need to write it as:
Private Host moHost = New Host();
Private ExchangeList moExchanges = New ExhangeList();
Related
Basically I am loading a JSON object that contains combinations of values available or not at run time, so I need to know when a specific property is modified to then toggle all the other browsable etc.. and though that the PropertyChange event was the perfect way to handle it.
So I can add an event handler to get triggered on my expandoobject like this:
Dim test As Object = new ExpandoObject
AddHandler CType(test, INotifyPropertyChanged).PropertyChanged, AddressOf expando_PropertyChanged
and the handler is as basic as it gets
Public Shared Sub expando_PropertyChanged(ByVal sender As Object, ByVal e As PropertyChangedEventArgs)
Debug.Print("Property {0} set or changed", e.PropertyName)
End Sub
so far this works, if I add or modify a property right after that, I get notified.
however if I return this and set it as the selectedobject of my propertygrid, I cannot get the event to trigger.
I'm using a custom PropertyDescriptor and ICustomTypeDescriptor to set a few other attributes for the propertygrid, so I assumed it might be as easy as setting the attribute
<RefreshProperties(RefreshProperties.All)>
but I cannot find a way to override the Refresh in the PropertyDescriptor unlike Browsable or readonly, which kinda makes sense as the property grid would need to know ahead of time that it needs to be refreshable.
So I could not make the INotifyPropertyChanged work with the expando, it would work with a dynamicObject where I would implement it myself but that was requiring too much of a rewrite for me.
I ended up add a lambda on my expando that I call on the PropertyDescriptor SetValue
CType(_expando, Object).toggleSwitches.Invoke(_expando, _name, value)
note the use of Invoke here in vb.net that was also a PITA but I found this guy who had the same issue as I did: https://github.com/dotnet/vblang/issues/226
It is not necessary to use invoke in C# and as 99% of the examples are in C# it took me more time than I wanted to implement it.
Hopefully this will help someone too.
here is the lambda if interested as well:
_expando.toggleSwitches = Sub(obj As Object, caller As String, value As Object)
Debug.Print(caller & " " & value.ToString())
End Sub
I am storing some program values in my Web.config file and would like to use them in my Code.
When i try to set the value like this.
Private Const Security As String = ConfigurationManager.AppSettings("jwtKey")
i get the error Constant expression is required. Is there a way to make this work or do i have to assign the value to each function in my controller which needs access to this constant.
An option is to use the ReadOnly attribute:
Private ReadOnly Security As String = ConfigurationManager.AppSettings("jwtKey")
From the MSDN article:
Specifies that a variable or property can be read but not written.
Just what you are describing, assign a value to a variable but do not allow it to be changed.
This what a constructor is for
Class MyController
Private Const Security As String
Public Sub New
Security = ConfigurationManager.AppSettings("jwtKey")
End Sub
If you're using DI, you could pass all the relevant options in as a single object
suppose I declare a class like this:
Class tst
Public Props As New Dictionary(Of String, MyProp)
End Class
and added properties something along these lines:
Dim t As New tst
t.Props.Add("Source", new MyProp(3))
but now want to access it like this:
t.Source
how can I create a getter without knowing the name of the getter?
Ok, if you insist on "auto-vivifying", the only way I know of to do something like that is to generate the code as a string, and then compile it at runtime using the classes in the System.CodeDom.Compiler namespace. I've only ever used it to generate complete classes from scratch, so I don't know if you could even get it to work for what need to add properties to an already existing class, but perhaps you could if you compiled extension methods at runtime.
The .NET framework includes multiple implementations of the CodeDomeProvider class, one for each language. You will most likely be interested in the Microsoft.VisualBasic.VBCodeProvider class.
First, you'll need to create a CompilerParameters object. You'll want to fill its ReferencedAssemblies collection property with a list of all the libraries your generated code will need to reference. Set the GenerateExecutable property to False. Set GenerateInMemory to True.
Next, you'll need to create a string with the source code you want to compile. Then, call CompileAssemblyFromSource, passing it the CompilerParameters object and the string of source code.
The CompileAssemblyFromSource method will return a CompilerResults object. The Errors collection contains a list of compile errors, if there are any, and the CompiledAssembly property will be a reference to your compiled library (as an Assembly object). To create an instance of your dynamically compiled class, call the CompiledAssembly.CreateInstance method.
If you're just generating a small amount of code, it's pretty quick to compile it. But if it's a lot of code, you may notice an impact on performance.
Here's a simple example of how to generate a dynamic class containing a single dynamic property:
Option Strict Off
Imports System.CodeDom.Compiler
Imports Microsoft.VisualBasic
Imports System.Text
Public Class Form3
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim code As StringBuilder = New StringBuilder()
code.AppendLine("Namespace MyDynamicNamespace")
code.AppendLine(" Public Class MyDynamicClass")
code.AppendLine(" Public ReadOnly Property WelcomeMessage() As String")
code.AppendLine(" Get")
code.AppendLine(" Return ""Hello World""")
code.AppendLine(" End Get")
code.AppendLine(" End Property")
code.AppendLine(" End Class")
code.AppendLine("End Namespace")
Dim myDynamicObject As Object = generateObject(code.ToString(), "MyDynamicNamespace.MyDynamicClass")
MessageBox.Show(myDynamicObject.WelcomeMessage)
End Sub
Private Function generateObject(ByVal code As String, ByVal typeName As String) As Object
Dim parameters As CompilerParameters = New CompilerParameters()
parameters.ReferencedAssemblies.Add("System.dll")
parameters.GenerateInMemory = True
parameters.GenerateExecutable = False
Dim provider As VBCodeProvider = New VBCodeProvider()
Dim results As CompilerResults = provider.CompileAssemblyFromSource(parameters, code)
If results.Errors.HasErrors Then
Throw New Exception("Failed to compile dynamic class")
End If
Return results.CompiledAssembly.CreateInstance(typeName)
End Function
End Class
Note, I never use Option Strict Off, but for the sake of simplicity in this example, I turned it off so I could simply call myDynamicObject.WelcomeMessage without writing all the reflection code myself.
Calling methods on objects using reflection can be painful and dangerous. Therefore, it can be helpful to provide a base class or interface in a shared assembly which is referenced by both the generated assembly, and the fixed assembly which calls the generated assembly. That way, you can use the dynamically generated objects through a strongly typed interface.
I figured based on your question that you were just more used to dynamic languages like JavaScript, so you were just thinking of a solution using the wrong mindset, not that you really needed to or even should be doing it this way. But, it is definitely useful in some situations to know how to do this in .NET. It's definitely not something you want to be doing on a regular basis, but, if you need to support custom scripts to perform complex validation or data transformations, something like this can be very useful.
using VB.Net2010 I need to call a C# DLL
The problem I have is accessing the procedures inside the class
The dll is referenced OK.
MYDLL is the namespace
which contains a public class Myclass
within MyClass are public procedures
sub New(MyString1 as string, MySTring2 as string)
sub ProgramStart(myString as string)
All I can see is MYDLL.Myclass
I can't see the procedures New and ProgramStart.
Viewing the references in the Object Browser I can see these procedures.
Any help appreciated.
Thanks
Ben
You need to create an instance of the object before being able to call instance methods:
Dim instance as MyClass = New MyClass("foo", "bar")
instance.ProgramStart("my string")
Long term lurker, first time poster here.
I have written a class to model an object in vb.net, using vs2008 and framework 2.0. I am serializing the class to an XML file for persistent storage. I do this with a method in the class like this:
Public Sub SaveAs(ByVal filename As String)
Dim writer As New Xml.Serialization.XmlSerializer(GetType(MyNamespace.MyClass))
Dim file As New System.IO.StreamWriter(filename)
writer.Serialize(file, Me)
file.Close()
End Sub
I now want to do a similar thing but reading the class from file to the current instance, like this:
Public Sub New(ByVal filename As String)
Dim reader = New Xml.Serialization.XmlSerializer(GetType(MyNamespace.MyClass))
Dim file = New System.IO.StreamReader(FullPath)
Me = CType(reader.Deserialize(file), MyNamespace.MyClass)
End Sub
However, I cannot assign anything to “Me”. I’ve tried creating a temporary object to hold the file contents then copying each property and field over to the current instance. I iterated over the properties (using Reflection), but this soon gets messy, dealing with ReadOnly collection properties, for example. If I just copy each property manually I will have to remember to modify the procedure whenever I add a property in the future, so that sounds like a recipe for disaster.
I know that I could just use a separate function outside the class but many built-in .NET classes can instantiate themselves from file e.g. Dim bmp As New Bitmap(filename As String) and this seems very intuitive to me.
So can anyone suggest how to load a class into the current instance in the Sub New procedure? Many thanks in advance for any advice.
I'd put a shared load function on the class, that returned the newly de-serialised object.
e.g.
Public Class MyClass
...
Public shared Function Load(ByVal filename As String) as MyClass
Dim reader = New Xml.Serialization.XmlSerializer(GetType(MyNamespace.MyClass))
Dim file = New System.IO.StreamReader(FullPath)
Return CType(reader.Deserialize(file), MyNamespace.MyClass)
End Sub
End Class
...
Dim mine as MyClass = MyClass.Load("MyObject.Xml");
Hope this helps
Alternatively,
Encapsulate the data of your class in an inner, private class.
The properties on your outer visible class delegate to the inner class.
Then Serialising and De-serialising happens on the inner class, you can then have a ctor that takes the file name, de-serialises the inner hidden object, and assigns it to the classes data store.
The "New" method in VB.Net is a constructor for the class. You can't call it for an existing instance, as the whole purpose of the method is to create new instances; it's just not how the language works. Try naming the method something like "ReadFrom" or "LoadFrom" instead.
Additionally, given those methods, I would try to implement them using a Factory Pattern. The ReadFrom method would be marked Shared and return the new instance. I would also make the method more generic. My main ReadFrom() method would accept an open textreader or xmlreader or even just a stream, rather than a file name. I would then have overloads that converts a file name into a stream for reading and calls the main method.
Of course, that assumes I use that pattern in the first place. .Net already has great support for xml serialization built into the platform. Look into the System.Xml.Serialization.XmlSerializer class and associated features.