Attempt to Add Instance of Class Fails - c#

I'm trying to work with a C# USB HID library (Mike O'Brien's open-source HIDLibrary) from my VB.NET application. I was able to make calls to methods in one of the classes easily. However, another method I'd like to call into in a different class isn't working. I can't access it directly by invoking the namespace and class name like I did for the other class, as VS complains "that a reference to a non-shared member requires an object reference". The class is public, so I think I *should" be able to call into it, but OK, so I try to add an object reference in my app, and it complains "Overload resolution failed because no "New" is accessible". The two classes (one of which "works", the other of which doesn't) appear to be set up virtually identically: they're both declared public, as are both of the methods I'm trying to call into.
I'm still a bit new to C#, and OOP in general, so pardon the newb question.
The full classes are pretty big, so I'm going to attempt to only include the "relevant" parts, but if I'm leaving something out, please let me know.
How the class I'd like to access is defined:
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
namespace HidLibrary
{
public class HidDevice : IHidDevice
{ ...
And the method itself I'm attempting to call:
public bool ReadFeatureData(out byte[] data, byte reportId = 0)
The way I've set up my VB.NET app to call into this dll:
Imports HidLibrary
Public Class DeviceIDTest
Dim HIDDeviceObj As New HidLibrary.HidDevice
And finally my attempt at a method call:
If HidDeviceObj.ReadFeatureData(InBuff, reportID) Then
Return InBuff
Else
Return False
End If

The constructor for HidDevice is internal, so it can only be called from other classes in the HidLibrary assembly, which is why you get the "Overload resolution failed because no "New" is accessible" error. Since the class is public, that probably implies that there is some other way to create instances. I have never used this library, but from a quick glance it looks like maybe you are supposed to use one of the static methods on HidDevices, i.e. GetDevice or one of the Enumerate methods, to access instances of HidDevice.
For example (completely untested code!):
Dim data() As Byte
For Each device In HidDevices.Enumerate()
If device.ReadFeatureData(data) Then
' Do something with data?
End If
Next

Related

Use Internal Class in C# Harmony Patch

I'm pretty new to c#, and I'm using Harmony patches to make a mod for a video game. The method I'm trying to patch is a private method which takes an internal class instance as a parameter. I've been able to use reflection to handle private methods in a few other patches, but when I try to add the internal parameter, I get a build error saying the class is inaccessible due to it's protection level.
I was trying to use the solution from this question, but I think I'm having some scope issues. Right now, I have something like
using System;
...
using System.Reflection;
using HarmonyLib;
using namespacesFromGame; // Including namespace where the internal is declared
...
namespace MyMod
{
[HarmonyPatch(typeof(GameClass))]
class MyPatch
{
Type MyInternal = typeof(GameClass).Assembly.GetType("GameInternal");
public static bool MethodPatch(GameClass__instance,..., MyInternal myInternal, ...)
{
...
}
}
}
When I try to do this, it tells me The type or namespace name 'MyInternal' cannot be found.
Where should I be putting my MyInternal declaration so it can be used as a parameter to MethodPatch, and so I will also be able to use the myInternal instance in the patch?
In C# you cannot declare the type of a property with another variable.
I see two solutions to this problem.
You can either do this :
using System;
...
using HarmonyLib;
using namespacesFromGame; // Including namespace where the internal is
namespace MyMod
{
[HarmonyPatch(typeof(GameClass))]
class MyPatch
{
public static bool MethodPatch(GameClass __instance,..., object myInternal, ...)
{
...
// do reflexion to access the method, the field and prop the object
}
}
}
This should work; but if you are new to C# the reflection may not necessarily be the easiest thing to do and it can quickly make your code unreadable.
Or do this :
You can publicise (make public) the dll you want to use. If you do this, you will have access to all classes, methods and ect... By doing this you will only have to use the desired type. But, you will have to compile your code in unstable.
For publicise, i found two github repo :
https://github.com/rwmt/Publicise
https://github.com/iRebbok/APublicizer
(you can also create your own but I think that to start it would be better to take one already made)
It will require republishing the assembly each time there is an update if your mod is outdated.
I also create modes on unity games. This is the solution I use and some FrameWork for modding uses to.
I don't know if there are performance impacts of using unstable code and calling private methods.
I advise you this solution, you would get cleaner code and you will have access to code more easily. But that is my personal opinion.

How do properly set up my common C# code so I can access them with a using directive?

I want to be able organize my most common code elements so that they can be "included" with a using statement similar to
using System;
using System.IO;
I am able to do this to a certain extent, but because of C# rules about namespaces and classes, I am unable to access my stuff directly, I always have to add it to a class and then access it by .item.
For example if I make a C# file named MyStuff.cs as follows:
namespace MyStuff
{
public static class MyClass
{
public static int MyCode(...)
{
...
}
}
}
I have to use it in my other code like this:
using MyStuff
...
int result = MyClass.MyCode(...);
...
I would like to be able to just access it like this (without the MyClass):
using MyStuff
...
int result = MyCode(...);
...
But I can't get that to work. I read somewhere that adding the "static" to the class they are in then the dot notation would not be needed, but that does not appear to be true.
Can anybody explain how to do this, or am I stuck with the extra layer?
Thanks!
I don't think it can be done.
In order to something to be accessed directly from within a namespace, it has to be an object. Functions cannot be directly put inside a namespace.
You can achieve what you want by making use of extension method by writing an extension method for instances of the 'Object' class (which is more of a hack). But you will still have to invoke it this way, this.MyCode().
Another solution is to have a superclass where you have this function MyCode() and inherit the place where you are going to use MyCode() from there but I am pretty sure that you have already considered something which is as basic as that.

Are System, console, Namespace classes or already instances?

I’m very new to programming. Actually less than one month back, I couldn’t name even 3 programming languages. So I’m really new to this.
After I understood the class concept and the object concept in OOP in general, I then realised that every single item present in the whole program is either an object or a class ready to give off objects.
Classes are non other than descriptions of objects, which are the main and sole players.
Moreover, functions or method are non other than sort of behavioural manifestation of an existing object.
( I wonder if the code line that we write for a function to be executed, the line of code in itself is a new object that refers to the existing original object that will perform the function we want , as part of its behaviour )
Now, If what I mentioned was near to be correct, What confused me next in my journey to understand OOP as a world wherein every single item is an object being utilised or destroyed, or brought into existence out of a class (blueprint ), which is nothing but a modifiable written description for objects how to be born.
What confused me here is the nature of “system”, “console”, and “namespace” each one of these, is it an object, so that we can call and utilise it without instantiating, or they are special classes readily instantiated as the program runs, or just ordinary classes ( which contradicts everything I understood ), because I can see "system" and "console" called and utilised only, and never instantiated ( just like an object )
Now, namespace seems to be a class that is instantiated into an object in the written script: ( namespace "the application name" { } ) but neither "system" nor "console" seems to be instantiated by programmer!
System is a namespace, Console is a static class inside the namespace System.
Static classes are classes which do not need to be created with the new keyword, and there is only one instance per application (excluding templated static classes - which you don't need to worry about for the moment)
Console can be written like this:
namespace System { //Namespace defined here!
public static class Console { //Static class defined here!
public static void WriteLine() { //Static method defined here!
//Implementation goes here
}
}
}
Note the keyword static when declaring the class. Removing this keyword would turn it into a normal class, and you'd have to use it like this:
var console = new System.Console();
console.WriteLine();
Based on the comments from Bauss and Physician about static methods.
You can write this, as well:
public class MyClass
{
public static void DoSomethingStatically()
{
}
public void DoSomethingNormally()
{
}
}
Now, you can do this:
MyClass.DoSomethingStatically();
but you cannot do:
MyClass.DoSomethingNormally();
To use the second method, you must create an instance:
var myClass = new MyClass();
myClass.DoSomethingNormally();
Note:
You cannot call a static method on an instance, so it is invalid to do the following:
var myClass = new MyClass();
myClass.DoSomethingStatically();
You can think of namespaces as containers of classes. System is a namespace which contains the Console class. Console is a special kind of class called a static class. A static class is denoted by the static keyword. The Console class's declaration would look something like this:
namespace System {
public static class Console {
//lots of stuff...
}
}
Actually you can read the Console class's source code in http://referencesource.microsoft.com
A static class cannot be instantiated. It just does its own work. It doesn't have objects. One of reasons is that it doesn't make sense to have objects. For example, the Math class is a static class because it doesn't make sense to say "Let's create a Math object!". Because Math is not like Cows or Streams or BinaryFormatters, which all are non static classes Generally, anything that you can prefix with "a" is not static. "a Stream", "a BinaryFormatter" etc.
Now for the namespace concept. You know sometimes the same word may mean different stuff depending on the context. e.g. Stream, in a programming context it means a file stream or some other kind of streams. But in a casual conversation, you say stream to mean a stream of water or something like that. So now you have to create two stream classes but there's a name conflict! That's why we have namespaces. Let's look at a real example. There are at least 2 classes called Path, but they are in different namespaces so it's ok to have the same name. One is in the System.Drawing namespace and the other is in the System.IO namespace. We often refer to those two classes as "System.IO.Path" and "System.Drawing.Path". Or you can write using directives.
Conclusion:
Both System and Console are not objects. They are a namespace and a static class respectively. And the word namespace denotes a namespace so it's not an object either.

"Private" visibility modifier - how to handle differences when converting C# to VB?

The Background
I have converted the C# code below (found in TreeViewAdv file TreeColumn.cs) into VB.net code using the converter found at DeveloperFusion.com.
C#
using System;
//...(other using calls)
namespace Aga.Controls.Tree
{
[TypeConverter(typeof(TreeColumn.TreeColumnConverter)), DesignTimeVisible(false), ToolboxItem(false)]
public class TreeColumn : Component
{
private class TreeColumnConverter : ComponentConverter
{
public TreeColumnConverter()
: base(typeof(TreeColumn))
{
}
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return false;
}
}
}
//…Some, I believe, unrelated code
}
VB
Imports System.Collections.Generic
‘...(other Imports calls)
Namespace Aga.Controls.Tree
<TypeConverter(GetType(TreeColumn.TreeColumnConverter)), DesignTimeVisible(False), ToolboxItem(False)> _
Public Class TreeColumn
Inherits Component
Private Class TreeColumnConverter
Inherits ComponentConverter
Public Sub New()
MyBase.New(GetType(TreeColumn))
End Sub
Public Overrides Function GetPropertiesSupported(ByVal context As ITypeDescriptorContext) As Boolean
Return False
End Function
End Class
‘...some, I believe, unrelated code
End Class
The Problem
Access to TreeColumn.TreeColumnConverter in this line of the C# code is fine.
[TypeConverter(typeof(TreeColumn.TreeColumnConverter)), DesignTimeVisible(false), ToolboxItem(false)]
However, VB.Net does not allow access to that member in the converted line:
The error description reads: Aga.Controls.Tree.TreeColumn.TreeColumnConverter' is not accessible in this context because it is 'Private'. However, in both cases TreeColumn.TreeColumnConverter is declared Private.
The Question(s)
1.) The Why. As this is a learning project for me, I would like to know WHY the scopes are acting differently among the two languages. This is the more important question among the 2 of them.
2.) The How. What is the best way(s) to change the VB code to allow access of TreeColumnConverter to the identified line of code without opening up the scope to the point that it potentially creates naming confusions elsewhere? I COULD just declare it Public, but I imagine there is a more correct approach to this.
Things To Keep In Mind When Answering
1.) I know that in VB.net Private members are not available external to the object in which they were declared. So telling me this will not be helpful and in my mind is not an answer.
To me, it looks like that the different compilers use different philosophies when dealing with nested private types. C# says its OK to access it from an attribute on the higher level type, VB.NET says it's not. Maybe those philosophies weren't even intentional.
Anyway, to fix it in VB.NET you could use the TypeConverterAttribute constructor that uses a string instead of a Type, and put the fully-qualified nested type name as a string:
<TypeConverter("Aga.Controls.Tree.TreeColumn.TreeColumnConverter"), DesignTimeVisible(False), ToolboxItem(False)> _
Public Class TreeColumn
...
Ah, I believe I see your problem.
It's the namespaces.
VB.NET Chains the Namespaces.
Namespace Aga.Controls.Tree in vb.net would actually be your project's default namespace concatenated with the namespace declared in the file.
It would actually be Aga.Controls.Tree.Aga.Controls.Tree so it likely just can't get to the scope it needs to be because it's pointing to the wrong namespace.
C#, you fully qualify namespaces... DevFusion's converter (same as the one used in SharpDevelop IDE) doesn't know this.

Reusable Class Library Implementation

I've built a reusable Class Library to encapsulate my Authentication logic. I want to be able to reuse the compiled *.dll across multiple projects.
What I've got works. But, something about how I'm making the reference, or how my Class Library is structured isn't quite right. And I need your help to figure out what I'm doing-wrong/not-understanding...
I've got a Class Library (Authentication.dll) which is structured like this:
namespace AUTHENTICATION
{
public static class authentication
{
public static Boolean Authenticate(long UserID, long AppID) {...}
//...More Static Methods...//
}
}
In my dependent project I've added a reference to Authentication.dll, and I've added a using directive...
using AUTHENTICATION;
With this structure I can call my Authenticate method, from my dependent project, like so...
authentication.Authenticate(1,1)
I'd like to be able to not have to include that "authentication." before all calls to methods from this Class Library. Is that possible? If so, what changes do I need to make to my Class Library, or how I'm implementing it in my dependent project?
In C# a function cannot exist without a class. So you always need to define something for it, being a class for a static method or an object for an object method.
The only option to achieve that would be to declare a base class in the Authentication assembly from which you inherit in the dependent projects.
You could expose Authenticate as a protected method (or public works too), and call it without specifying the class name.
public class MyClassInDependentProject : authentication
{
public void DoSomething(int userId, long appId)
{
var success = Authenticate(userId, appId);
…
}
}
That said, you'll quickly find this to be a bad design. It conflates a cross-cutting concern with all sorts of other classes, and those classes are now precluded from inheriting from any other class.
Composition is a core principle of object-oriented programming, and we have the idiom "Favor composition over inheritance." This simply means that we break down complexity into manageable chunks (classes, which become instantiated as objects), and then compose those objects together to handle complex processing. So, you have encapsulated some aspect of authentication in your class, and you provide that to other classes compositionally so they can use it for authentication. Thinking about it as an object with which you can do something helps, conceptually.
As an analogy, think about needing to drill a hole in the top of your desk. You bring a drill (object) into your office (class). At that point, it wouldn't make sense to simply say "On," because "On" could be handled by your fan, your lamp, your PC, etc. (other objects in your class). You need to specify, "Drill On."
If you are making a class library in C# you should learn to use the naming conventions that exists: Design Guidelines for Developing Class Libraries
Here is how you should name namespaces: https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/interface
C# is also an object oriented language, hence the need of classes (using Authentication as you should name your class).
It also seems like the data source is hard coded. Your class library users (even if it's just you) might want to configure the data source.
Google about singleton and why it's considered to be an anti pattern today (in most cases).
You are obliged to use Class in order to invoke your method, just
When is static class just NameClass.Method
When is not static, you must create instance, ClassName ob = new ClassName(); ob.Method();
The format of a call like this is class.method, and you really can't escape using the "class" moniker even with the "using" designation. Something has to "host" the function.
I don't think what you are asking for is possible without using the base class method Jay mentioned. If all you want is to simplify the syntax whenever you call Authenticate() however, this silly solution (adding an extra method in each class that needs to do authentication) may be just what you want:
private static void DoAuth(long UserID, long AppID){
authentication.Authenticate(UserID, AppID)
}
If the ID's are always the same within some context, you could also overload it:
private static void DoAuth(){
DoAuth(1,1)
}
Yes, this does mean you have to add more code wherever you want to do the authentication (that's why it's silly! ;) ). It does also however, also reduce this:
authentication.Authenticate(1,1);
...into this:
DoAuth();
I leave the cost / benefit analysis of this up to you..
I know I am some 3 years late but here goes nothing.
To keep your code cleaner and more readable you should create a new namespace for all the re-usable code that you want to have. Then in that namespace have the Authentication Class and Authenticate Function.
To use this you can easily set a using on your namespace and use the function as you are doing like
Authentication.Authenticate()
But to use
Authenticate()
by itself you can always do
using MyNamespace.Authentication;
and in your code use Authenticate Function directly.

Categories